Python 中網頁抓取的當前問題和錯誤以及解決它們的技巧!

王林
發布: 2024-08-23 06:04:31
原創
938 人瀏覽過

介紹

您好!我是 Max,來自烏克蘭的 Python 開發人員,一位在網頁抓取、資料分析和處理方面擁有專業知識的開發人員。

我的網頁抓取之旅始於 2016 年,當時我正在為一家小公司解決潛在客戶開發挑戰。最初,我使用了現成的解決方案,例如 Import.io 和 Kimono Labs。然而,我很快就遇到了諸如阻塞、資料提取不準確和效能問題等限制。這促使我學習Python。在那些輝煌的日子裡,requests 和 lxml/beautifulsoup 足以從大多數網站提取資料。如果您知道如何使用線程,那麼您已經是一位受人尊敬的專家了:)

我們的一位社群成員撰寫此部落格作為對 Crawlee 部落格的貢獻。如果您想向 Crawlee 博客貢獻此類博客,請透過我們的 Discord 頻道與我們聯繫。

克勞利和阿皮皮

這是Apify和Crawlee的官方開發者社群。 | 8318 會員

Current problems and mistakes of web scraping in Python and tricks to solve them! 不和諧網站

身為自由工作者,多年來我為產品建立了小型解決方案和大型、複雜的資料探勘系統。

今天,我想討論 2024 年使用 Python 進行網頁抓取的現實。我們將看看我有時會看到的錯誤以及您會遇到的問題,並為其中一些問題提供解決方案。

讓我們開始吧。

只需接受請求和 beautifulsoup 即可開始賺很多錢......

不,這不是那種文章。

1.“我從伺服器收到了 200 回應,但這是一個不可讀的字元集。”

是的,這可能會令人驚訝。但我在六年前、四年前和 2024 年就看到過客戶和開發者發來的這則訊息。幾個月前我在 Reddit 上讀過一篇關於這個問題的貼文。

讓我們來看一個簡單的程式碼範例。這將適用於 requests、httpx 和 aiohttp,只需全新安裝且無需擴充。

import httpx

url = 'https://www.wayfair.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = httpx.get(url, headers=headers)

print(response.content[:10])
登入後複製

列印結果將類似:

b'\x83\x0c\x00\x00\xc4\r\x8e4\x82\x8a'
登入後複製

這不是一個錯誤 - 這是一個完全有效的伺服器回應。它以某種方式編碼。

答案就在 Accept-Encoding 標頭中。在上面的範例中,我只是從瀏覽器複製它,因此它列出了我的瀏覽器支援的所有壓縮方法:「gzip、deflate、br、zstd」。 Wayfair 後端支援使用「br」(即 Brotli)進行壓縮,並將其用作最有效的方法。

如果上面列出的庫的標準依賴項中沒有 Brotli 依賴項,則可能會發生這種情況。但是,如果您已經安裝了 Brotli,它們都支援從此格式解壓縮。

因此,安裝適當的函式庫就足夠了:

pip install Brotli
登入後複製

這將使您獲得列印結果:

b'<!DOCTYPE '
登入後複製

透過使用擴充功能進行安裝,aiohttp 和 httpx 可以獲得相同的結果:

pip install aiohttp[speedups]
pip install httpx[brotli]
登入後複製

順便說一句,加入 brotli 依賴項是我對crawlee-python 的第一個貢獻。他們使用 httpx 作為基本 HTTP 客戶端。

您可能還注意到不久前出現了一種新的受支援的資料壓縮格式 zstd。我還沒有看到任何後端使用它,但是httpx將在0.28.0以上的版本中支援解壓縮。我已經在我的專案中使用它來壓縮伺服器回應轉儲;它在使用 aiofiles 的非同步解決方案中顯示出令人難以置信的效率。

我見過的這種情況最常見的解決方案是開發人員簡單地停止使用 Accept-Encoding 標頭,從而從伺服器獲得未壓縮的回應。為什麼這麼糟? Wayfair 的首頁未壓縮時約 1 MB,壓縮後約 0.165 MB。

因此,在沒有此標頭的情況下:

  • 您增加了網路頻寬的負載。
  • 如果您使用有流量的代理,則會增加每個請求的成本。
  • 您增加了伺服器網際網路頻寬的負載。
  • 你暴露了自己是一個爬蟲,因為任何瀏覽器都使用壓縮。

但我認為問題比這更深。許多網頁抓取開發人員根本不明白他們所使用的標頭的作用。因此,如果這適用於您,那麼當您從事下一個專案時,請閱讀這些內容;他們可能會讓您大吃一驚。

2.「我在隱身瀏覽器中使用標頭,但收到 403 回應」。這是 Johnn-...我是說,Cloudflare

是的,沒錯。 2023 年不僅為我們帶來了 ChatGPT 等大型語言模型,還改進了 Cloudflare 保護。

那些長期從事網頁抓取的人可能會說,「好吧,我們已經處理過 DataDome、PerimeterX、InCapsula 等。」

但是 Cloudflare 改變了遊戲規則。它是世界上最大的 CDN 提供者之一,為大量網站提供服務。因此,許多站點都可以使用其服務,並且進入門檻相當低。這使得它與前面提到的技術完全不同,這些技術是在他們想要保護網站免受抓取時有目的地實施的。

Cloudflare 就是為什麼當您開始閱讀另一門有關「如何使用 requests 和 beautifulsoup 進行網頁抓取」的課程時,您可以立即關閉它的原因。因為你所學到的東西很可能根本無法在任何「體面」的網站上運作。

讓我們來看另一個簡單的程式碼範例:

from httpx import Client

client = Client(http2=True)

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = client.get(url, headers=headers)

print(response)
登入後複製

當然,回應將是 403。

如果我們使用curl會怎麼樣?

curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' -s -o /dev/null -w "%{http_code}\n"
登入後複製

還有403。

為什麼會發生這種情況?

由於 Cloudflare 使用開發人員中流行的許多 HTTP 用戶端的 TLS 指紋,網站管理員還可以根據這些指紋自訂 Cloudflare 阻止客戶端的積極程度。

對於curl,我們可以這樣解決:

curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' --tlsv1.3 -s -o /dev/null -w "%{http_code}\n"
登入後複製

You might expect me to write here an equally elegant solution for httpx, but no. About six months ago, you could do the "dirty trick" and change the basic httpcore parameters that it passes to h2, which are responsible for the HTTP2 handshake. But now, as I'm writing this article, that doesn't work anymore.

There are different approaches to getting around this. But let's solve it by manipulating TLS.

The bad news is that all the Python clients I know of use the ssl library to handle TLS. And it doesn't give you the ability to manipulate TLS subtly.

The good news is that the Python community is great and implements solutions that exist in other programming languages.

The first way to solve this problem is to use tls-client

This Python wrapper around the Golang library provides an API similar to requests.

pip install tls-client
登入後複製
from tls_client import Session

client = Session(client_identifier="firefox_120")

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = client.get(url, headers=headers)

print(response)
登入後複製

The tls_client supports TLS presets for popular browsers, the relevance of which is maintained by developers. To use this, you must pass the necessary client_identifier. However, the library also allows for subtle manual manipulation of TLS.

The second way to solve this problem is to use curl_cffi

This wrapper around the C library patches curl and provides an API similar to requests.

pip install curl_cffi
登入後複製
from curl_cffi import requests

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = requests.get(url, headers=headers, impersonate="chrome124")

print(response)
登入後複製

curl_cffi also provides TLS presets for some browsers, which are specified via the impersonate parameter. It also provides options for subtle manual manipulation of TLS.

I think someone just said, "They're literally doing the same thing." That's right, and they're both still very raw.

Let's do some simple comparisons:

Feature tls_client curl_cffi
TLS preset + +
TLS manual + +
async support - +
big company support - +
number of contributors - +

顯然,curl_cffi 在這次比較中獲勝。但作為一個活躍用戶,我不得不說,有時會出現一些非常奇怪的錯誤,我只是不確定該如何處理。老實說,到目前為止,它們都還很原始。

我想我們很快就會看到其他函式庫可以解決這個問題。

有人可能會問,Scrapy 怎麼樣?老實說:我並沒有真正跟上他們的更新。但我還沒有聽說 Zyte 做了任何事情來繞過 TLS 指紋識別。因此,開箱即用的 Scrapy 也會被阻止,但沒有什麼可以阻止您在 Scrapy Spider 中使用curl_cffi。

3. 無頭瀏覽器和 Cloudflare Turnstile 怎麼樣?

是的,有時我們需要使用無頭瀏覽器。雖然說實話,但從我的角度來看,即使明顯沒有必要,它們也被頻繁使用。

即使在無頭的情況下,Cloudflare 的人們也成功地透過創造一個名為 Cloudflare Turnstile 的怪物來讓普通網路爬蟲的生活變得困難。

要測試不同的工具,您可以使用此示範頁面。

要快速測試庫是否適用於瀏覽器,您應該從檢查通常的非無頭模式開始。您甚至不需要使用自動化;只需使用所需的庫打開站點並手動操作即可。

哪些函式庫值得為此檢查?

候選人 #1 劇作家 + 隱密劇作家

它會被阻止並且不會讓你解決驗證碼。

Playwright 是一個很棒的瀏覽器自動化函式庫。然而,開發人員明確表示,他們不打算將其開發為網頁抓取工具。

而且我還沒有聽說過任何Python專案可以有效解決這個問題。

候選#2 unDetected_chromedriver

它會被阻止並且不會讓你解決驗證碼。

這是一個相當常見的函式庫,用於在 Python 中使用無頭瀏覽器,在某些情況下,它允許繞過 Cloudflare Turnstile。但在目標網站上,它被阻止了。此外,在我的專案中,我還遇到至少兩種 Cloudflare 阻止 unDetected_chromedriver 的情況。

總的來說,unDetected_chromedriver 對於您的專案來說是一個很好的庫,特別是因為它在底層使用了很好的舊 Selenium。

候選人 #3 botasaurus-driver

它允許您在點擊後跳過驗證碼。

我不知道它的開發者是如何做到這一點的,但它確實有效。它的主要特點是它是專門為網頁抓取而開發的。它還有一個更高級別的庫可供使用 - botasaurus。

缺點是,到目前為止,它還很原始,botasaurus-driver 沒有文檔,並且有一個相當具有挑戰性的 API 來使用。

總而言之,您用於無頭瀏覽的主庫很可能是 unDetected_chromedriver。但在一些特別具有挑戰性的情況下,您可能需要使用botasaurus。

4. 框架呢?

高級框架旨在透過讓我們專注於業務邏輯來加速和簡化開發,儘管我們經常在靈活性和控制方面付出代價。

那麼,2024 年網頁抓取的架構是什麼?

刮痧

談論 Python 網頁抓取框架就不能不提到 Scrapy。 Scrapinghub(現在的 Zyte)於 2008 年首次發布它。 16 年來,它一直作為一個開源庫開發,開發公司在此基礎上建立其業務解決方案。

說一下Scrapy的優點,可以單獨寫一篇文章。但我要強調的是他們兩個:

  • 歷年發佈的海量教學
  • 中間件庫由社群編寫並正在擴展其功能。例如,scrapy-playwright。

但是有什麼缺點呢?

近年來,Zyte更專注於開發自己的平台。 Scrapy 大多只修復。

  • 缺乏繞過反抓取系統的開發。你必須自己實現它們,但是為什麼需要框架呢?
  • Scrapy 最初是使用非同步框架 Twisted 開發的。僅在 2.0 版本中新增了對 asyncio 的部分支援。查看原始程式碼,您可能會注意到為此目的添加的一些解決方法。

因此,對於沒有網頁抓取保護的網站來說,Scrapy 是一個良好且經過驗證的解決方案。您需要開發必要的解決方案並將其添加到框架中,以繞過反抓取措施。

波塔龍

使用瀏覽器自動化進行網頁抓取的新框架,基於 botasaurus-driver 建置。首次提交於 2023 年 5 月 9 日進行。

先來說說它的優點:

  • 允許您使用 botasaurus-driver 繞過任何 Claudflare 保護以及許多其他保護。
  • 快速入門的良好文件

缺點包括:

  • 僅瀏覽器自動化,不適用於 HTTP 用戶端。
  • 與botasaurus-driver緊密耦合;如果將來出現更好的東西,您將無法輕易取代它。
  • 沒有異步,只有多執行緒。
  • 目前,它還很原始,仍然需要修復才能穩定運作。
  • 目前可用的訓練教材很少。

這是一個很好的框架,可以快速建立基於瀏覽器自動化的網路爬蟲。它缺乏靈活性和對 HTTP 用戶端的支持,這對於像我這樣的用戶來說是一個難題。

Python 的 Crawlee

Python 生態系中網路抓取的新框架。首次提交於 2024 年 1 月 10 日做出,並於 2024 年 7 月 5 日在媒體空間發布。

Current problems and mistakes of web scraping in Python and tricks to solve them! apify / 爬蟲-python

Crawlee——一個用於 Python 的網頁抓取和瀏覽器自動化庫,用於建立可靠的爬蟲。擷取 AI、LLM、RAG 或 GPT 的資料。從網站下載 HTML、PDF、JPG、PNG 和其他文件。適用於 BeautifulSoup、Playwright 和原始 HTTP。有頭模式和無頭模式。透過代理輪換。

Current problems and mistakes of web scraping in Python and tricks to solve them!
網頁抓取和瀏覽器自動化庫

Current problems and mistakes of web scraping in Python and tricks to solve them! Current problems and mistakes of web scraping in Python and tricks to solve them! Current problems and mistakes of web scraping in Python and tricks to solve them! Current problems and mistakes of web scraping in Python and tricks to solve them!

Crawlee 涵蓋了端到端的爬行和抓取,並且幫助您建立可靠的抓取工具。快。

? Crawlee for Python 開放給早期採用者!

即使使用預設配置,您的爬蟲也會看起來幾乎像人類一樣,並且在現代機器人保護的雷達下飛行。 Crawlee 為您提供了在網路上抓取連結、抓取資料並將其持久儲存為機器可讀格式的工具,而無需擔心技術細節。由於豐富的設定選項,如果預設設定無法滿足您的專案需求,您幾乎可以調整 Crawlee 的任何方面。

在 Crawlee 專案網站上查看完整文件、指南和範例 ?

我們還有 Crawlee 的 TypeScript 實現,您可以在您的專案中探索和利用它。請造訪我們的 GitHub 儲存庫,以了解 GitHub 上 Crawlee for JS/TS 的更多資訊。

安裝

我們…


在 GitHub 上查看


由 Apify 開發,是其著名的 JS 框架crawlee 的 Python 改編版,於 2019 年 7 月 9 日首次發布。

由於這是市場上的全新解決方案,因此目前正處於積極的設計和開發階段。社區也積極參與其開發。所以,我們可以看到curl_cffi的使用已經在討論中了。之前討論過創建自己的基於 Rust 的客戶端的可能性。希望公司不要放棄這個想法。

來自 Crawlee 團隊:
「是的,我們肯定會在未來幾年不斷改進 Crawlee for Python。」

因為我個人希望看到由大公司開發和維護的 Python HTTP 用戶端。 Rust 很好地展示了自己作為 Python 的庫語言的能力。讓我們至少記住 Ruff 和 Pydantic v2。

優點:

該框架是由網頁抓取市場中的一家老牌公司開發的,該公司在該領域擁有完善的專業知識。

  • 支援瀏覽器自動化和 HTTP 用戶端。
  • 完全異步,基於 asyncio。
  • 活躍的開發階段和媒體活動。開發者傾聽社群的聲音,在這個階段非常重要。

另外一點,它有一個非常好的模組化架構。如果開發人員引入在多個 HTTP 用戶端之間切換的功能,我們將獲得一個相當靈活的框架,使我們能夠輕鬆更改所使用的技術,只需開發團隊的簡單實作。

不足:

  • 框架是新的。目前可用的訓練教材很少。
  • 目前,它還很原始,仍然需要修復才能穩定運行,以及方便的配置介面。 - 除了更改會話和代理程式之外,目前沒有任何方法可以繞過反抓取系統。但它們正在討論中。

我相信crawlee-python 的成功主要取決於社群。由於教程數量較少,不適合初學者。然而,經驗豐富的開發人員可能會決定嘗試它而不是 Scrapy。

從長遠來看,它可能是比 Scrapy 和 Botasaurus 更好的解決方案。它已經提供了靈活的工具來使用 HTTP 用戶端、開箱即用地自動化瀏覽器以及在它們之間快速切換。然而,它缺乏繞過抓取保護的工具,它們在未來的實現可能是您選擇框架的決定性因素。

結論

如果您已經讀到這裡,我想您會發現它很有趣,甚至可能有幫助:)

產業正在改變並帶來新的挑戰,如果您專業從事網頁抓取,則必須密切注意情況。在其他一些領域,您將仍然是使用過時技術製造產品的開發人員。但在現代網頁抓取中,您成為一名開發人員,製作的網頁抓取工具根本不起作用。

此外,不要忘記您是更大的 Python 社群的一員,您的知識可用於開發使我們所有人的事情發生的工具。正如您所看到的,您需要的許多工具現在正在建置中。

我很高興閱讀您的評論。另外,如果您需要網頁抓取專家或只是想討論這篇文章,您可以在以下平台找到我:Github、Linkedin、Apify、Upwork、Contra。

感謝您的關注:)

以上是Python 中網頁抓取的當前問題和錯誤以及解決它們的技巧!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!