這是我最想推薦給程式設計師們看的基於Python3.4實現的爬蟲書

互聯網包含了迄今為止最有用的數據集,並且大部分可以免費公開訪問。但是,這些數據難以複用。它們被嵌入在網站的結構和樣式當中,需要抽取出來才能使用。從網頁中抽取數據的過程又稱為網絡爬蟲,隨著越來越多的信息被髮布到網絡上,網絡爬蟲也變得越來越有用。

今天介紹的這一本書《用Python寫網絡爬蟲(第2版)》是Python網絡爬蟲暢銷圖書全新升級版,上一版年度暢銷近4萬冊,而本書針對Python 3.x編寫,提供示例完整源碼和實例網站搭建源碼,確保你可以在本地成功復現爬取網站環境,並保障網站的穩定性與可靠性以及代碼運行結果的可再現性。 書中使用的所有代碼均已使用Python 3.4+測試通過,並且可以在異步社區下載到。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

查看更多詳情鏈接 https://www.epubit.com/book/detail/33225

“網絡爬蟲何時有用”

假設我有一個鞋店,並且想要及時瞭解競爭對手的價格。我可以每天訪問他們的網站,與我店鋪中鞋子的價格進行對比。但是,如果我店鋪中的鞋類品種繁多,或是希望能夠更加頻繁地查看價格變化的話,就需要花費大量的時間,甚至難以實現。再舉一個例子,我看中了一雙鞋,想等到它促銷時再購買。我可能需要每天訪問這家鞋店的網站來查看這雙鞋是否降價,也許需要等待幾個月的時間,我才能如願盼到這雙鞋促銷。上述這兩個重複性的手工流程,都可以利用本書介紹的網絡爬蟲技術實現自動化處理。

在理想狀態下,網絡爬蟲並不是必需品,每個網站都應該提供API,以結構化的格式共享它們的數據。然而在現實情況中,雖然一些網站已經提供了這種API,但是它們通常會限制可以抓取的數據,以及訪問這些數據的頻率。另外,網站開發人員可能會變更、移除或限制其後端API。總之,我們不能僅僅依賴於API去訪問我們所需的在線數據,而是應該學習一些網絡爬蟲技術的相關知識。

“本書基於Python 3”

在本書中,我們將完全使用Python 3進行開發。Python軟件基金會已經宣佈Python 2將會被逐步淘汰,並且只支持到2020年;出於該原因,我們和許多其他Python愛好者一樣,已經將開發轉移到對Python 3的支持當中,在本書中我們將使用3.6版本。本書代碼將兼容Python 3.4+的版本。

如果你熟悉Python Virtual Environments或Anaconda的使用,那麼你可能已經知道如何在一個新環境中創建Python 3了。如果你希望以全局形式安裝Python 3,那麼我們推薦你搜索自己使用的操作系統的特定文檔。就我而言,我會直接使用Virtual EnvironmentWrapper,這樣就可以很容易地對不同項目和Python版本使用多個不同的環境了。使用Conda環境或虛擬環境是最為推薦的,這樣你就可以輕鬆變更基於項目需求的依賴,而不會影響到你正在做的其他工作了。對於初學者來說,我推薦使用Conda,因為其需要的安裝工作更少一些。

“編寫第一個網絡爬蟲”

為了抓取網站,我們首先需要下載包含有感興趣數據的網頁,該過程一般稱為

爬取(crawling)。爬取一個網站有很多種方法,而選用哪種方法更加合適,則取決於目標網站的結構。本文中,我們首先會探討如何安全地下載網頁,然後會介紹如下3種爬取網站的常見方法:

爬取網站地圖;

使用數據庫ID遍歷每個網頁;

跟蹤網頁鏈接。

到目前為止,我們交替使用了抓取和爬取這兩個術語,接下來讓我們先來定義這兩種方法的相似點和不同點。

1.1抓取與爬取的對比

根據你所關注的信息以及站點內容和結構的不同,你可能需要進行網絡抓取或是網站爬取。那麼它們有什麼區別呢?

網絡抓取通常針對特定網站,並在這些站點上獲取指定信息。網絡抓取用於訪問這些特定的頁面,如果站點發生變化或者站點中的信息位置發生變化的話,則需要進行修改。例如,你可能想要通過網絡抓取查看你喜歡的當地餐廳的每日特色菜,為了實現該目的,你需要抓取其網站中日常更新該信息的部分。

與之不同的是,網絡爬取通常是以通用的方式構建的,其目標是一系列頂級域名的網站或是整個網絡。爬取可以用來收集更具體的信息,不過更常見的情況是爬取網絡,從許多不同的站點或頁面中獲取小而通用的信息,然後跟蹤鏈接到其他頁面中。

除了爬取和抓取外,我們還會在第8章中介紹網絡爬蟲。爬蟲可以用來爬取指定的一系列網站,或是在多個站點甚至整個互聯網中進行更廣泛的爬取。

一般來說,我們會使用特定的術語反映我們的用例。在你開發網絡爬蟲時,可能會注意到它們在你想要使用的技術、庫和包中的區別。在這些情況下,你對不同術語的理解,可以幫助你基於所使用的術語選擇適當的包或技術(例如,是否只用於抓取?是否也適用於爬蟲?)。

1.2下載網頁

要想抓取網頁,我們首先需要將其下載下來。下面的示例腳本使用Python的urllib模塊下載URL。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

當傳入URL參數時,該函數將會下載網頁並返回其HTML。不過,這個代碼片段存在一個問題,即當下載網頁時,我們可能會遇到一些無法控制的錯誤,比如請求的頁面可能不存在。此時,urllib會拋出異常,然後退出腳本。安全起見,下面再給出一個更穩建的版本,可以捕獲這些異常。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

現在,當出現下載或URL錯誤時,該函數能夠捕獲到異常,然後返回None。

1.重試下載

下載時遇到的錯誤經常是臨時性的,比如服務器過載時返回的503 Service Unavailable錯誤。對於此類錯誤,我們可以在短暫等待後嘗試重新下載,因為這個服務器問題現在可能已經解決。不過,我們不需要對所有錯誤都嘗試重新下載。如果服務器返回的是404 Not Found這種錯誤,則說明該網頁目前並不存在,再次嘗試同樣的請求一般也不會出現不同的結果。

互聯網工程任務組(Internet Engineering Task Force)定義了HTTP錯誤的完整列表,從中可以瞭解到4xx錯誤發生在請求存在問題時,而5xx錯誤則發生在服務端存在問題時。所以,我們只需要確保download函數在發生5xx錯誤時重試下載即可。下面是支持重試下載功能的新版本代碼。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

現在,當download函數遇到5xx錯誤碼時,將會遞歸調用函數自身進行重試。此外,該函數還增加了一個參數,用於設定重試下載的次數,其默認值為兩次。我們在這裡限制網頁下載的嘗試次數,是因為服務器錯誤可能暫時還沒有恢復。想要測試該函數,可以嘗試下載http://httpstat.us/500,該網址會始終返回500錯誤碼。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

從上面的返回結果可以看出,download函數的行為和預期一致,先嚐試下載網頁,在接收到500錯誤後,又進行了兩次重試才放棄。

2.設置用戶代理

默認情況下,urllib使用Python-urllib/``3.x作為用戶代理下載網頁內容,其中3.x是環境當前所用Python的版本號。如果能使用可辨識的用戶代理則更好,這樣可以避免我們的網絡爬蟲碰到一些問題。此外,也許是因為曾經歷過質量不佳的Python網絡爬蟲造成的服務器過載,一些網站還會封禁這個默認的用戶代理。

因此,為了使下載網站更加可靠,我們需要控制用戶代理的設定。下面的代碼對download函數進行了修改,設定了一個默認的用戶代理‘wswp’(即Web Scraping with Python的首字母縮寫)。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

現在,如果你再次嘗試訪問meetup.com,就能夠看到一個合法的HTML了。我們的下載函數可以在後續代碼中得到複用,該函數能夠捕獲異常、在可能的情況下重試網站以及設置用戶代理。

1.3網站地圖爬蟲

在第一個簡單的爬蟲中,我們將使用示例網站robots.txt文件中發現的網站地圖來下載所有網頁。為了解析網站地圖,我們將會使用一個簡單的正則表達式,從標籤中提取出URL。

我們需要更新代碼以處理編碼轉換,因為我們目前的download函數只是簡單地返回了字節。下面是該示例爬蟲的代碼。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

現在,運行網站地圖爬蟲,從示例網站中下載所有國家或地區頁面。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

正如上面代碼中的download方法所示,我們必須更新字符編碼才能利用正則表達式處理網站響應。Python的read方法返回字節,而正則表達式期望的則是字符串。我們的代碼依賴於網站維護者在響應頭中包含適當的字符編碼。如果沒有返回字符編碼頭部,我們將會把它設置為默認值UTF-8,並抱有最大的希望。當然,如果返回頭中的編碼不正確,或是編碼沒有設置並且也不是UTF-8的話,則會拋出錯誤。還有一些更復雜的方式用於猜測編碼(參見https://pypi.python.org/pypi/chardet),該方法非常容易實現。

到目前為止,網站地圖爬蟲已經符合預期。不過正如前文所述,我們無法依靠Sitemap文件提供每個網頁的鏈接。下一節中,我們將會介紹另一個簡單的爬蟲,該爬蟲不再依賴於Sitemap文件。

1.4ID遍歷爬蟲

本節中,我們將利用網站結構的弱點,更加輕鬆地訪問所有內容。下面是一些示例國家(或地區)的URL。

http://example.python-scraping.com/view/Afghanistan-1

http://example.python-scraping.com/view/Australia-2

http://example.python-scraping.com/view/Brazil-3

可以看出,這些URL只在URL路徑的最後一部分有所區別,包括國家(或地區)名(作為頁面別名)和ID。在URL中包含頁面別名是非常普遍的做法,可以對搜索引擎優化起到幫助作用。一般情況下,Web服務器會忽略這個字符串,只使用ID來匹配數據庫中的相關記錄。下面我們將其移除,查看http://example.python-scraping.com/view/1,測試示例網站中的鏈接是否仍然可用。測試結果如圖1.1所示。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

圖1.1

從圖1.1中可以看出,網頁依然可以加載成功,也就是說該方法是有用的。現在,我們就可以忽略頁面別名,只利用數據庫ID來下載所有國家(或地區)的頁面了。下面是使用了該技巧的代碼片段。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

現在,我們可以使用該函數傳入基礎URL。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

在這段代碼中,我們對ID進行遍歷,直到出現下載錯誤時停止,我們假設此時抓取已到達最後一個國家(或地區)的頁面。不過,這種實現方式存在一個缺陷,那就是某些記錄可能已被刪除,數據庫ID之間並不是連續的。此時,只要訪問到某個間隔點,爬蟲就會立即退出。下面是這段代碼的改進版本,在該版本中連續發生多次下載錯誤後才會退出程序。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

上面代碼中實現的爬蟲需要連續5次下載錯誤才會停止遍歷,這樣就很大程度上降低了遇到記錄被刪除或隱藏時過早停止遍歷的風險。

在爬取網站時,遍歷ID是一個很便捷的方法,但是和網站地圖爬蟲一樣,這種方法也無法保證始終可用。比如,一些網站會檢查頁面別名是否在URL中,如果不是,則會返回404 Not Found錯誤。而另一些網站則會使用非連續大數作為ID,或是不使用數值作為ID,此時遍歷就難以發揮其作用了。例如,Amazon使用ISBN作為可用圖書的ID,這種編碼包含至少10位數字。使用ID對ISBN進行遍歷需要測試數十億次可能的組合,因此這種方法肯定不是抓取該站內容最高效的方法。

正如你一直關注的那樣,你可能已經注意到一些TOO MANY REQUESTS下載錯誤信息。現在無須擔心它,我們將會在1.5節的“高級功能”部分中介紹更多處理該類型錯誤的方法。

1.5鏈接爬蟲

到目前為止,我們已經利用示例網站的結構特點實現了兩個簡單爬蟲,用於下載所有已發佈的國家(或地區)頁面。只要這兩種技術可用,就應當使用它們進行爬取,因為這兩種方法將需要下載的網頁數量降至最低。不過,對於另一些網站,我們需要讓爬蟲表現得更像普通用戶,跟蹤鏈接,訪問感興趣的內容。

通過跟蹤每個鏈接的方式,我們可以很容易地下載整個網站的頁面。但是,這種方法可能會下載很多並不需要的網頁。例如,我們想要從一個在線論壇中抓取用戶賬號詳情頁,那麼此時我們只需要下載賬號頁,而不需要下載討論貼的頁面。本文使用的鏈接爬蟲將使用正則表達式來確定應當下載哪些頁面。下面是這段代碼的初始版本。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

要運行這段代碼,只需要調用link_crawler函數,並傳入兩個參數:要爬取的網站URL以及用於匹配你想跟蹤的鏈接的正則表達式。對於示例網站來說,我們想要爬取的是國家(或地區)列表索引頁和國家(或地區)頁面。

我們查看站點可以得知索引頁鏈接遵循如下格式:

http://example.python-scraping.com/index/1

http://example.python-scraping.com/index/2

國家(或地區)頁遵循如下格式:

http://example.python-scraping.com/view/Afghanistan-1

http://example.python-scraping.com/view/Aland-Islands-2

因此,我們可以用/(index|view)/這個簡單的正則表達式來匹配這兩類網頁。當爬蟲使用這些輸入參數運行時會發生什麼呢?你會得到如下所示的下載錯誤。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

可以看出,問題出在下載/index/1時,該鏈接只有網頁的路徑部分,而沒有協議和服務器部分,也就是說這是一個相對鏈接。由於瀏覽器知道你正在瀏覽哪個網頁,並且能夠採取必要的步驟處理這些鏈接,因此在瀏覽器瀏覽時,相對鏈接是能夠正常工作的。但是,urllib並沒有上下文。為了讓urllib能夠定位網頁,我們需要將鏈接轉換為絕對鏈接的形式,以便包含定位網頁的所有細節。如你所願,Python的urllib中有一個模塊可以用來實現該功能,該模塊名為parse。下面是link_crawler的改進版本,使用了urljoin方法來創建絕對路徑。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

當你運行這段代碼時,會看到雖然下載了匹配的網頁,但是同樣的地點總是會被不斷下載到。產生該行為的原因是這些地點相互之間存在鏈接。比如,澳大利亞鏈接到了南極洲,而南極洲又鏈接回了澳大利亞,此時爬蟲就會繼續將這些URL放入隊列,永遠不會到達隊列尾部。要想避免重複爬取相同的鏈接,我們需要記錄哪些鏈接已經被爬取過。下面是修改後的link_crawler函數,具備了存儲已發現URL的功能,可以避免重複下載。

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

當運行該腳本時,它會爬取所有地點,並且能夠如期停止。最終,我們得到了一個可用的鏈接爬蟲!

本文摘自《用Python寫網絡爬蟲(第2版)》

這是我最想推薦給程序員們看的基於Python3.4實現的爬蟲書

《用Python寫網絡爬蟲》紙書鏈接 https://www.epubit.com/book/detail/33225

史上首本Python網絡爬蟲圖書全新升級版

針對Python 3.x編寫

提供示例完整源碼和實例網站搭建源碼

本書目錄

(滑動手機查看)

第1章 網絡爬蟲簡介 1

1.1 網絡爬蟲何時有用 1

1.2 網絡爬蟲是否合法 2

1.3 Python 3 3

1.4 背景調研 4

1.4.1 檢查robots.txt 4

1.4.2 檢查網站地圖 5

1.4.3 估算網站大小 6

1.4.4 識別網站所用技術 7

1.4.5 尋找網站所有者 9

1.5 編寫第一個網絡爬蟲 11

1.5.1 抓取與爬取的對比 11

1.5.2 下載網頁 12

1.5.3 網站地圖爬蟲 15

1.5.4 ID遍歷爬蟲 17

1.5.5 鏈接爬蟲 19

1.5.6 使用requests庫 28

1.6 本章小結 30

第2章 數據抓取 31

2.1 分析網頁 32

2.2 3種網頁抓取方法 34

2.2.1 正則表達式 35

2.2.2 Beautiful Soup 37

2.2.3 Lxml 39

2.3 CSS選擇器和瀏覽器控制檯 41

2.4 XPath選擇器 43

2.5 LXML和家族樹 46

2.6 性能對比 47

2.7 抓取結果 49

2.7.1 抓取總結 50

2.7.2 為鏈接爬蟲添加抓取回調 51

2.8 本章小結 55

第3章 下載緩存 56

3.1 何時使用緩存 57

3.2 為鏈接爬蟲添加緩存支持 57

3.3 磁盤緩存 60

3.3.1 實現磁盤緩存 62

3.3.2 緩存測試 64

3.3.3 節省磁盤空間 65

3.3.4 清理過期數據 66

3.3.5 磁盤緩存缺點 68

3.4 鍵值對存儲緩存 69

3.4.1 鍵值對存儲是什麼 69

3.4.2 安裝Redis 70

3.4.3 Redis概述 71

3.4.4 Redis緩存實現 72

3.4.5 壓縮 74

3.4.6 測試緩存 75

3.4.7 探索requests-cache 76

3.5 本章小結 78

第4章 併發下載 79

4.1 100萬個網頁 79

4.2 串行爬蟲 82

4.3 多線程爬蟲 83

4.4 線程和進程如何工作 83

4.4.1 實現多線程爬蟲 84

4.4.2 多進程爬蟲 87

4.5 性能 91

4.6 本章小結 94

第5章 動態內容 95

5.1 動態網頁示例 95

5.2 對動態網頁進行逆向工程 98

5.3 渲染動態網頁 104

5.3.1 PyQt還是PySide 105

5.3.2 執行Java 106

5.3.3 使用WebKit與網站交互 108

5.4 渲染類 111

5.5 本章小結 117

第6章 表單交互 119

6.1 登錄表單 120

6.2 支持內容更新的登錄腳本擴展 128

6.3 使用Selenium實現自動化表單處理 132

6.4 本章小結 135

第7章 驗證碼處理 136

7.1 註冊賬號 137

7.2 光學字符識別 140

7.3 處理複雜驗證碼 144

7.4 使用驗證碼處理服務 144

7.4.1 9kw入門 145

7.4.2 報告錯誤 150

7.4.3 與註冊功能集成 151

7.5 驗證碼與機器學習 153

7.6 本章小結 153

第8章 Scrapy 154

8.1 安裝Scrapy 154

8.2 啟動項目 155

8.2.1 定義模型 156

8.2.2 創建爬蟲 157

8.3 不同的爬蟲類型 162

8.4 使用shell命令抓取 163

8.4.1 檢查結果 165

8.4.2 中斷與恢復爬蟲 167

8.5 使用Portia編寫可視化爬蟲 170

8.5.1 安裝 170

8.5.2 標註 172

8.5.3 運行爬蟲 176

8.5.4 檢查結果 176

8.6 使用Scrapely實現自動化抓取 177

8.7 本章小結 178

第9章 綜合應用 179

9.1 Google搜索引擎 179

9.2 Facebook 184

9.2.1 網站 184

9.2.2 Facebook API 186

9.3 Gap 188

9.4 寶馬 192

9.5 本章小結 196

京東預售鏈接 https://item.m.jd.com/product/12397576.html

噹噹預售鏈接 http://product.m.dangdang.com//product.php?pid=25303745&host=product.dangdang.com

今日互動

學會爬蟲,你最想做的第一件事兒是什麼?為什麼?截止時間7月21日17時,留言+轉發本活動到朋友圈,小編將抽獎選出2名讀者

贈送紙書2本,文末留言點贊最多的自動獲得圖書1本。

在“異步圖書”微信後臺回覆“關注”,即可免費獲得2000門在線視頻課程


分享到:


相關文章: