天才教育網(wǎng)合作機(jī)構(gòu) > 編程語言培訓(xùn)機(jī)構(gòu) > Python培訓(xùn)機(jī)構(gòu) >

好學(xué)教育咨詢

歡迎您!
朋友圈

4008508622

全國統(tǒng)一學(xué)習(xí)專線 9:00-21:00

位置:編程語言培訓(xùn)問答 > Python培訓(xùn)問答 > python網(wǎng)絡(luò)爬蟲的工具_(dá)常見工具介紹

python網(wǎng)絡(luò)爬蟲的工具_(dá)常見工具介紹

日期:2025-02-07     瀏覽:83    來源:好學(xué)教育咨詢
核心提示:接著我的上一篇文章《網(wǎng)頁爬蟲完全指南》,這篇文章將涵蓋幾乎所有的 Python 網(wǎng)頁爬取工具。我們從*基本的開始講起,逐步涉及到當(dāng)


接著我的上一篇文章《網(wǎng)頁爬蟲完全指南》,這篇文章將涵蓋幾乎所有的 Python 網(wǎng)頁爬取工具。我們從*基本的開始講起,逐步涉及到當(dāng)前*前沿的技術(shù),并且對它們的利弊進(jìn)行分析。

當(dāng)然,我們不能全面地介紹每個工具,但這篇文章應(yīng)該足以讓你很好地知道哪些工具做什么,以及何時使用每一種工具。

注意: 本文中所涉及到的 Python 均指 Python3。

本文要點:

  • Web 基礎(chǔ)
  • 手動創(chuàng)建一個 socket 并且發(fā)送 HTTP 請求
  • urllib3 & LXML
  • requests & BeautifulSoup
  • Scrapy(爬蟲框架)
  • Selenium(瀏覽器自動化測試框架) & Chrome——headless
  • 總結(jié)

Web 基礎(chǔ)

互聯(lián)網(wǎng)其實是 非常復(fù)雜的 ——我們通過瀏覽器瀏覽一個簡單的網(wǎng)頁時,其背后其實涉及到許多技術(shù)和概念。 我并不打算對其進(jìn)行逐一講解, 但我會告訴你如果想要從網(wǎng)絡(luò)中爬取數(shù)據(jù)需要了解哪些*重要的知識。

HyperText Transfer Protocol(超文本傳輸協(xié)議,簡稱 HTTP)

HTTP 采用 C/S 模型 , 在 HTTP 客戶機(jī)(如 瀏覽器,Python 程序, curl(命令行工具),Requests 等等) 創(chuàng)建一個連接并向 HTTP 服務(wù)器(如 Nginx,Apache 等)發(fā)送信息("我想瀏覽產(chǎn)品頁")。

然后服務(wù)器返回一個響應(yīng)(如 HTML 代碼)并且關(guān)閉連接。與 FTP 這些有狀態(tài)協(xié)議不同,HTTP 的每個事務(wù)都是獨立的,因此被稱為無狀態(tài)協(xié)議。

基本上,當(dāng)你在瀏覽器中鍵入網(wǎng)站地址時,HTTP 請求如下所示:

GET /product/ HTTP/1.1Host: example.comAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/web\p,*/*;q=0.8Accept-Encoding: gzip, deflate, sdch, brConnection: keep-aliveUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

在這個請求的*行, 你可以獲得如下的信息:

  • 使用 Get 動詞或者方法, 意味著我們從指定的路徑 /product/ 請求數(shù)據(jù)。還有其他 HTTP 謂詞,你可以在這里看到完整的列表。
  • HTTP 協(xié)議的版本。在本教程中,我們將重點討論 HTTP1。
  • 多個 header 字段。

以下是*重要的 header 字段:

  • Host: 服務(wù)器的域名。如果沒有給出端口號,則默認(rèn)為 80* . *
  • User-Agent: 包含有關(guān)發(fā)起請求的客戶端的信息, 包括 OS 等信息。比如說上面的例子中,表明了我的瀏覽器(Chrome),在 Mac OS X 系統(tǒng)上. 這個header字段很重要,因為它要么用于統(tǒng)計(有多少用戶訪問我的移動和桌面網(wǎng)站),要么用于防止機(jī)器人的任何違規(guī)行為。因為這些報頭是由客戶端發(fā)送的,所以可以使用一種名為"報頭欺騙"的技術(shù)對其進(jìn)行修改。這正是我們的爬蟲程序要做的,使他們看起來像一個正常的網(wǎng)頁瀏覽器。
  • Accept: 表明響應(yīng)可接受的內(nèi)容類型。有許多不同的內(nèi)容類型和子類型: text/plain,text/html, image/jpeg, application/json …
  • cookie:name1=value1; name2=value2… 這個 header 字段包含一組鍵值對。這些稱為會話 cookie,是網(wǎng)站用來驗證用戶身份和在瀏覽器中存儲數(shù)據(jù)的工具。比如說,當(dāng)你登錄時填寫完賬號密碼并提交,服務(wù)器會檢查你輸入的賬號密碼是否正確。如果無誤,它將重定向并且在你的瀏覽器中注入一個會話cookie,瀏覽器會將此cookie連同隨后的每個請求一起發(fā)送給服務(wù)器。
  • Referrer : 這個字段包含請求實際URL的URL。網(wǎng)站通過此header字段來判斷用戶的來源,進(jìn)而調(diào)整該用戶的網(wǎng)站權(quán)限。例如,很多新聞網(wǎng)站都有付費訂閱,只允許你瀏覽 10% 的帖子。但是,如果用戶是來自像 Reddit 這樣的新聞聚合器,就能瀏覽全部內(nèi)容。網(wǎng)站使用 referrer 頭字段來進(jìn)行檢查這一點。 有時,我們不得不偽造這個 header 字段來獲取我們想要提取的內(nèi)容。

當(dāng)然 header 字段不僅僅是這些。你可以在此處獲取更多的信息。

服務(wù)器將返回類似如下的響應(yīng):

HTTP/1.1 200 OKServer: nginx/1.4.6 (Ubuntu) Content-Type: text/html; charset=utf-8 ta charset="utf-8" /> ...[HTML CODE]

在*行我們能看到一個HTTP代碼 200 OK 。這意味著我們的請求成功了。至于請求頭,有很多 HTTP 代碼,分為四個常見的類:2XX 用于成功請求,3XX 用于重定向,4XX 用于錯誤請求(**的是404未找到),5XX 用于服務(wù)器錯誤。

如果你使用 Web 瀏覽器發(fā)送 HTTP 請求,它將解析 HTML 代碼,獲取所有*終資源(Javascript、CSS 和圖像文件),并將結(jié)果呈現(xiàn)到主窗口中。

在下一節(jié)中,我們將看到使用 Python 執(zhí)行 HTTP 請求的不同方法,并從響應(yīng)中提取我們想要的數(shù)據(jù)。

手動創(chuàng)建一個 socket 并且發(fā)送 HTTP 請求

Socket(套接字)

在 Python 中執(zhí)行 HTTP 請求的*基本方法是打開一個 socket 并手動發(fā)送 HTTP 請求:

import socketHOST = 'www.google.com'  # Server hostname or IP addressPORT = 80        # Portclient_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_address = (HOST, PORT)client_socket.connect(server_address)request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'client_socket.sendall(request_header)response = ''while True:    recv = client_socket.recv(1024)    if not recv:        break    response += str(recv)

現(xiàn)在我們有了 HTTP 響應(yīng),從其中提取數(shù)據(jù)的*基本方法就是使用正則表達(dá)式。

正則表達(dá)式

正則表達(dá)式(RE, or Regex)是字符串的搜索模式。你可以使用 regex 在更大的文本中搜索特定的字符或單詞,例如,你可以識別網(wǎng)頁上的所有電話號碼。你也可以輕松地替換字符串,例如,可以將格式較差的 HTML 中的所有大寫標(biāo)記用小寫標(biāo)記替換。還可以驗證一些輸入。

你可能想知道,為什么在進(jìn)行 Web 抓取時了解正則表達(dá)式很重要?畢竟,有各種不同的 Python 模塊來解析 HTML、XPath 和 CSS 選擇器。

在一個理想的語義世界中 ,數(shù)據(jù)很容易被機(jī)器讀取,信息被嵌入到相關(guān)的 HTML 元素和具有一定意義的屬性中。

但現(xiàn)實世界是混亂的,你經(jīng)常會在 p 元素中搜索大量的文本。當(dāng)你想要在這個巨大的文本塊中提取特定數(shù)據(jù)(如價格、日期或名稱)時,你必須使用正則表達(dá)式。

注意: 這篇文章只介紹了一小部分你可以用正則表達(dá)式做的事情。你可以通過這篇文章來練習(xí)正則表達(dá)式,以及通過這個很棒的博客來進(jìn)一步了解。

當(dāng)你的數(shù)據(jù)類似于下面這種的時候,正則表達(dá)式就能發(fā)揮很大的作用:

Price : 19.99$

我們可以使用 XPath 表達(dá)式選擇這個文本節(jié)點,然后使用這種 regex 提取 price。請記住,正則表達(dá)式模式是從左到右應(yīng)用的,每個源字符只使用一次。:

^Price\s:\s(\d+.\d{2})$

要提取 HTML 標(biāo)記中的文本,使用 regex 是很煩人的,但它是可行的:

import rehtml_content = '

Price : 19.99$

'

如你所見,通過 socket 手動發(fā)送 HTTP 請求并使用正則表達(dá)式解析響應(yīng)是可以完成的,但這很復(fù)雜。所以有更高級別的 API 可以使這個任務(wù)變得更容易。

urllib3 & LXML

說明: 我們在學(xué)習(xí) Python 中的 urllib 系列的庫的時候很容易感到迷茫。Python 除了有作為標(biāo)準(zhǔn)庫一部分的 urlib 和 urlib2,還有 urlib3。urllib2 在 Python3 中被分成很多模塊,不過 urllib3 在短期內(nèi)應(yīng)該不會成為標(biāo)準(zhǔn)庫的一部分。其實應(yīng)該有一篇單獨文章來討論這些令人困惑的細(xì)節(jié),在本篇中,我選擇只討論 urllib 3,因為它在 Python 世界中被廣泛使用。

urllib3 是一個高級包,它允許你對 HTTP 請求做任何你想做的事情。我們可以用更少的代碼行來完成上面的套接字操作:

import urllib3http = urllib3.PoolManager()r = http.request('GET', 'http://www.google.com')print(r.data)

比套接字版本要簡潔得多,對嗎?不僅如此,API 也很簡單,你可以輕松地做許多事情,比如添加 HTTP 頭、使用代理、發(fā)布表單等等。

例如,如果我們必須設(shè)置一些 header 字段來使用代理,我們只需這樣做:

import urllib3user_agent_header = urllib3.make_headers(user_agent="")pool = urllib3.ProxyManager(f'', headers=user_agent_header)r = pool.request('GET', 'https://www.google.com/')

看見沒?完全相同的行數(shù)。

然而,有些事情 urllib 3并不容易處理。如果要添加 cookie,則必須手動創(chuàng)建相應(yīng)的 header 字段并將其添加到請求中。

此外,urllib 3 還可以做一些請求不能做的事情,比如池和代理池的創(chuàng)建和管理,以及重試策略的控制。

簡單地說,urllib 3 在抽象方面介于請求和套接字之間,盡管它比套接字更接近請求。

為了解析響應(yīng),我們將使用 lxml 包和 XPath 表達(dá)式。

XPath

XPath 是一種使用路徑表達(dá)式在 XML 或 HTML 文檔中選擇節(jié)點或節(jié)點集的技術(shù)。與文檔對象模型(documentObjectModel)一樣,XPath 自 1999 年以來一直是 W3C 標(biāo)準(zhǔn)。即使 XPath 本身不是一種編程語言,它允許你編寫可以直接訪問特定節(jié)點或節(jié)點集的表達(dá)式,而無需遍歷整個 XML 或 HTML 樹。

可以將 XPath 看作一種專門用于 XML 或 HMTL 的正則表達(dá)式。

要使用 XPath 從 HTML 文檔中提取數(shù)據(jù),我們需要 3 件事:

  • HTML 文檔
  • 一些 XPath 表達(dá)式
  • 運行這些表達(dá)式的 XPath 引擎

首先,我們將使用我們通過 urllib 3 獲得的 HTML。我們只想從 Google 主頁中提取所有鏈接,所以我們將使用一個簡單的 XPath 表達(dá)式 //a ,并使用 LXML 來運行它。LXML 是一個快速易用的 XML 和 HTML 處理庫,支持 XPath。

安裝 :

pip install lxml

下面是前面片段之后的代碼:

from lxml import html

輸出如下:

https://books.google.fr/bkshp?hl=fr&tab=wphttps://www.google.fr/shopping?hl=fr&source=og&tab=wfhttps://www.blogger.com/?tab=wjhttps://photos.google.com/?tab=wq&pageId=nonehttp://video.google.fr/?hl=fr&tab=wvhttps://docs.google.com/document/?usp=docs_alc...https://www.google.fr/intl/fr/about/products?tab=wh

請記住,這個示例非常簡單,并沒有向你展示 XPath 有多強(qiáng)大。 (注意: 這個 XPath 表達(dá)式應(yīng)該更改為 //a/@href 為了避免在 links 中迭代以獲得它們的 href )。

如果你想了解更多關(guān)于 XPath 的知識,可以閱讀這個很棒的介紹文檔。這個 LXML 文檔 也編寫得很好,很適合基礎(chǔ)閱讀。.

XPath 表達(dá)式和 regexp 一樣很強(qiáng)大,是從 HTML 中提取信息的*快方法之一。雖然 XPath 也像 regexp 一樣很快就會變得凌亂,難以閱讀和維護(hù)。

requests & BeautifulSoup(庫)

python

下載量已經(jīng)超過 11,000,000 次的 Requests 庫是 Python 包中的佼佼者,它是 Python 使用*廣泛的包。

安裝:

pip install requests

使用 Requests 庫發(fā)送一個請求是非常容易的事情:

import requests

使用 Requests 庫可以很容易地執(zhí)行 POST 請求、處理 cookie 和查詢參數(shù)。

Hacker News 認(rèn)證

假設(shè)我們想要創(chuàng)建一個工具來自動提交我們的博客文章給 Hacker News 或任何其他論壇如 Buffer。在提交我們的鏈接之前,我們需要認(rèn)證到這些網(wǎng)站。這就是我們要通過 Requests 和 BeautifulSoup 做的事情!

下面是 Hacker News 登錄表單和相關(guān)的 DOM:

python

這個表單上有三個 標(biāo)簽。*個帶有 hidden 類型的名字為 "goto" 輸入,另外兩個是用戶名和密碼。

如果你在 Chrome 瀏覽器中提交表單,你會發(fā)現(xiàn)有很多事情發(fā)生:重定向和正在設(shè)置 cookie。這個 cookie 將由 Chrome 在每個后續(xù)請求上發(fā)送,以便服務(wù)器知道你已通過身份驗證。

通過 Requests 來做這些工作將會變得非常簡單,它將自動為我們處理重定向,而處理 cookie 則可以使用 _Session_Object 完成。

接下來我們需要的是 BeautifulSoup,它是一個 Python 庫,它將幫助我們解析服務(wù)器返回的 HTML,以確定我們是否登錄。

安裝:

pip install beautifulsoup4

所以我們要做的就是通過 POST 請求將這三個帶有我們登錄憑證的輸入發(fā)送到 /login 終端,并且驗證一個只在登錄成功時才出現(xiàn)的元素。

import requestsfrom bs4 import BeautifulSoupbase_URL = 'https://news.ycombinator.com'USERNAME = ""PASSWORD = ""s = requests.Session()data = {"gogo": "news", "acct": USERNAME, "pw": PASSWORD}r = s.post(f'{base_URL}/login', data=data)

我們可以嘗試提取主頁上的每一個鏈接,以了解更多關(guān)于 BeautifulSoup 的信息。

順便說一句,Hacker News 提供了一個功能強(qiáng)大的 API,所以我們這里只是以它為例,你真的應(yīng)該直接使用 API,而不是爬取它! _

我們需要做的*件事是觀察分析Hacker News主頁,以了解我們必須選擇的結(jié)構(gòu)和不同的 CSS 類。

我們可以看到所有的 posts 都在 里 ,因此,我們需要做的*件事是選擇所有這些標(biāo)記。通過下面這行代碼我們很容易實現(xiàn):

links = soup.findAll('tr', class_='athing')

然后,對于每個鏈接,我們將提取其 ID、標(biāo)題、url 和排名:

import requestsfrom bs4 import BeautifulSoupr = requests.get('https://news.ycombinator.com')soup = BeautifulSoup(r.text, 'html.parser')links = soup.findAll('tr', class_='athing')formatted_links = []for link in links:    data = {        'id': link['id'],        'title': link.find_all('td')[2].a.text,        "url": link.find_all('td')[2].a['href'],        "rank": int(links[0].td.span.text.replace('.', ''))    }    formatted_links.append(data)

正如你所看到的,Requests 和 BeautifulSoup 是提取數(shù)據(jù)和自動化實現(xiàn)各種操作(如填寫表單)的很好的庫。如果你想做大規(guī)模的網(wǎng)絡(luò)抓取項目,你仍然可以使用請求,但你需要自己處理很多事情。

在爬取大量網(wǎng)頁的時候,你需要處理很多事情:

  • 找到并行化代碼的方法,使代碼更高效
  • 處理錯誤
  • 存儲爬取的數(shù)據(jù)
  • 過濾和篩選數(shù)據(jù)
  • 控制請求速度,這樣就不會使服務(wù)器超載

幸運的是,我們可以使用工具處理所有這些事情。

Scrapy

python

scrapy 是一個強(qiáng)大的 Python Web 抓取框架。它提供了許多特性來異步下載、處理和保存網(wǎng)頁。它處理多線程、爬行(從鏈接到查找網(wǎng)站中的每個URL的過程)、站點地圖爬行等等。

Scrapy 還有一個名為 ScrapyShell 的交互模式。你可以使用 ScrapyShell 快速測試代碼,比如 XPath 表達(dá)式或 CSS 選擇器。

Scrapy 的缺點在于陡峭的學(xué)習(xí)曲線——有很多東西要學(xué)。

繼續(xù)上述 Hacker News 的例子,我們將編寫一個 ScrapySpider,它會抓取前 15 頁的結(jié)果,并將所有內(nèi)容保存在 CSV 文件中。

pip 安裝 Scrapy:

pip install Scrapy

然后,你可以使用 scrapycli 生成項目的樣板代碼:

scrapy startproject hacker_news_scraper


hacker_news_scraper/spider 我們將使用Spider的代碼創(chuàng)建一個新的 Python 文件:

from bs4 import BeautifulSoupimport scrapyclass HnSpider(scrapy.Spider):    name = "hacker-news"    allowed_domains = ["news.ycombinator.com"]    start_urls = [f'https://news.ycombinator.com/news?p={i}' for i in range(1,16)]    def parse(self, response):        soup = BeautifulSoup(response.text, 'html.parser')        links = soup.findAll('tr', class_='athing')        for link in links:        yield {        'id': link['id'],        'title': link.find_all('td')[2].a.text,        "url": link.find_all('td')[2].a['href'],        "rank": int(link.td.span.text.replace('.', ''))        }

Scrapy 中有很多規(guī)定,這里我們定義了一個啟動 URL 數(shù)組。屬性 name 將用于使用 Scrapy 命令行調(diào)用我們的 Spider。

數(shù)組中的每個 URL 調(diào)用解析方法。

然后,為了讓我們的爬蟲更好的在目標(biāo)網(wǎng)站上爬數(shù)據(jù),我們要對 Scrapy 進(jìn)行微調(diào)。

# Enable and configure the AutoThrottle extension (disabled by default)# See https://doc.scrapy.org/en/latest/topics/autothrottle.htmlAUTOTHROTTLE_ENABLED = True# The initial download delayAUTOTHROTTLE_START_DELAY = 5

你應(yīng)該一直把這個爬蟲程序一直運行著,它將通過分析響應(yīng)時間和調(diào)整并發(fā)線程的數(shù)量來確保目標(biāo)網(wǎng)站不會因為爬蟲而負(fù)載過大。

你可以使用 ScrapyCLI 運行下面的代碼并且設(shè)置不同的輸出格式(CSV、JSON、XML等)。

scrapy crawl hacker-news -o links.json

類似于這樣,*終爬取的結(jié)果會按照 json 的格式導(dǎo)出到一個名為 links 的 json 文件中

Selenium & Chrome —headless

對于大規(guī)模的網(wǎng)絡(luò)抓取任務(wù)來說,Scrapy 是非常好的。但是,如果需要爬取用 Javascript 框架編寫的單頁應(yīng)用程序,這是不夠的,因為它無法呈現(xiàn) Javascript 代碼。

爬取這些 SPAs 是很有挑戰(zhàn)性的,因為經(jīng)常涉及很多 Ajax 調(diào)用和 WebSocket 連接。如果性能存在問題,你將不得不逐個復(fù)制 Javascript 代碼,這意味著使用瀏覽器檢查器手動檢查所有網(wǎng)絡(luò)調(diào)用,并復(fù)制和你感興趣的數(shù)據(jù)相關(guān)的 Ajax 調(diào)用。

在某些情況下,涉及到的異步 HTTP 調(diào)用太多,無法獲取所需的數(shù)據(jù),在 headless 模式的瀏覽器中呈現(xiàn)頁面可能會更容易。

另一個很好的用例是對一個頁面進(jìn)行截圖。這是我們將要對 Hacker News 主頁做的事情(再次!)pip 安裝 Selenium 包:

pip install selenium

你還需要 Chromedriver:

brew install chromedriver

然后,我們只需從 Selenium 包中導(dǎo)入 Webriver,配置 Chrome的Headless=True,并設(shè)置一個窗口大小(否則它非常小):

from selenium import webdriverfrom selenium.webdriver.chrome.options import Options

然后你應(yīng)該得到一個很好的主頁截圖。

python

你可以使用 SeleniumAPI 和 Chrome 做更多的事情,比如:

  • 執(zhí)行 Javascript
  • 填寫表單
  • 點擊元素
  • 用 CSS 選擇器或 XPath 表達(dá)式提取元素

Selenium 和 headless 模式下的 Chrome 簡直是完美組合,能爬取到任何你想要爬取的數(shù)據(jù)。你可以將使用普通的 Chrome 瀏覽器所做的所有操作都設(shè)置為自動化。

Chrome *大的缺點是需要大量的內(nèi)存 /CPU 能力。通過一些微調(diào),你可以將每個 Chrome 實例的內(nèi)存占用減少到 300-400MB,但每個實例仍然需要一個 CPU 核心。

如果你想同時運行多個 Chrome 實例,你將需要強(qiáng)大的服務(wù)器(其成本迅速上升),以及持續(xù)監(jiān)視資源。

總結(jié)

我希望這個概述將幫助你選擇你的 Python 抓取工具,并希望你通過本文能有所收獲。

我在這篇文章中所介紹的工具都是我在做自己的項目 ScrapingNinja 時用過的,這個項目很簡單的網(wǎng)絡(luò)爬蟲 API。

這篇文章中提及的每一個工具,我之后都會單獨寫一篇博客來進(jìn)行深入闡述其細(xì)節(jié)。

不要猶豫,在評論中告訴我你還想知道關(guān)于爬蟲的哪些知識。我將會在下一篇文章中進(jìn)行講解分析。

Happy Scraping!

免責(zé)聲明:本信息由用戶發(fā)布,本站不承擔(dān)本信息引起的任何交易及知識產(chǎn)權(quán)侵權(quán)的法律責(zé)任!

本文由 好學(xué)教育咨詢 整理發(fā)布。更多培訓(xùn)課程,學(xué)習(xí)資訊,課程優(yōu)惠,課程開班,學(xué)校地址等學(xué)校信息,可以留下你的聯(lián)系方式,讓課程老師跟你詳細(xì)解答:
咨詢電話:4008508622

如果本頁不是您要找的課程,您也可以百度查找一下: