互聯網包含了迄今爲止最有用的數據集,而且大部分能夠免費公開訪問。可是,這些數據難以複用。它們被嵌入在網站的結構和樣式當中,須要抽取出來才能使用。從網頁中抽取數據的過程又稱爲網絡爬蟲,隨着愈來愈多的信息被髮布到網絡上,網絡爬蟲也變得愈來愈有用。
python
今天介紹的這一本書《用Python寫網絡爬蟲(第2版)》是Python網絡爬蟲暢銷圖書全新升級版,上一版年度暢銷近4萬冊,而本書針對Python 3.x編寫,提供示例完整源碼和實例網站搭建源碼,確保你能夠在本地成功復現爬取網站環境,並保障網站的穩定性與可靠性以及代碼運行結果的可再現性。 書中使用的全部代碼均已使用Python 3.4+測試經過,而且能夠在異步社區下載到。正則表達式
點擊封面查看更多詳情shell
「網絡爬蟲什麼時候有用」數據庫
假設我有一個鞋店,而且想要及時瞭解競爭對手的價格。我能夠天天訪問他們的網站,與我店鋪中鞋子的價格進行對比。可是,若是我店鋪中的鞋類品種繁多,或是但願可以更加頻繁地查看價格變化的話,就須要花費大量的時間,甚至難以實現。再舉一個例子,我看中了一雙鞋,想等到它促銷時再購買。我可能須要天天訪問這家鞋店的網站來查看這雙鞋是否降價,也許須要等待幾個月的時間,我才能如願盼到這雙鞋促銷。上述這兩個重複性的手工流程,均可以利用本書介紹的網絡爬蟲技術實現自動化處理。後端
在理想狀態下,網絡爬蟲並非必需品,每一個網站都應該提供API,以結構化的格式共享它們的數據。然而在現實狀況中,雖然一些網站已經提供了這種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 Environment Wrapper,這樣就能夠很容易地對不一樣項目和Python版本使用多個不一樣的環境了。使用Conda環境或虛擬環境是最爲推薦的,這樣你就能夠輕鬆變動基於項目需求的依賴,而不會影響到你正在作的其餘工做了。對於初學者來講,我推薦使用Conda,由於其須要的安裝工做更少一些。安全
「編寫第一個網絡爬蟲」服務器
爲了抓取網站,咱們首先須要下載包含有感興趣數據的網頁,該過程通常稱爲爬取(crawling)。爬取一個網站有不少種方法,而選用哪一種方法更加合適,則取決於目標網站的結構。本文中,咱們首先會探討如何安全地下載網頁,而後會介紹以下3種爬取網站的常見方法:
爬取網站地圖;
使用數據庫ID遍歷每一個網頁;
跟蹤網頁連接。
到目前爲止,咱們交替使用了抓取和爬取這兩個術語,接下來讓咱們先來定義這兩種方法的類似點和不一樣點。
根據你所關注的信息以及站點內容和結構的不一樣,你可能須要進行網絡抓取或是網站爬取。那麼它們有什麼區別呢?
網絡抓取一般針對特定網站,並在這些站點上獲取指定信息。網絡抓取用於訪問這些特定的頁面,若是站點發生變化或者站點中的信息位置發生變化的話,則須要進行修改。例如,你可能想要經過網絡抓取查看你喜歡的當地餐廳的每日特點菜,爲了實現該目的,你須要抓取其網站中平常更新該信息的部分。
與之不一樣的是,網絡爬取一般是以通用的方式構建的,其目標是一系列頂級域名的網站或是整個網絡。爬取能夠用來收集更具體的信息,不過更常見的狀況是爬取網絡,從許多不一樣的站點或頁面中獲取小而通用的信息,而後跟蹤連接到其餘頁面中。
除了爬取和抓取外,咱們還會在第8章中介紹網絡爬蟲。爬蟲能夠用來爬取指定的一系列網站,或是在多個站點甚至整個互聯網中進行更普遍的爬取。
通常來講,咱們會使用特定的術語反映咱們的用例。在你開發網絡爬蟲時,可能會注意到它們在你想要使用的技術、庫和包中的區別。在這些狀況下,你對不一樣術語的理解,能夠幫助你基於所使用的術語選擇適當的包或技術(例如,是否只用於抓取?是否也適用於爬蟲?)。
要想抓取網頁,咱們首先須要將其下載下來。下面的示例腳本使用Python的urllib
模塊下載URL。
urllib
會拋出異常,而後退出腳本。安全起見,下面再給出一個更穩建的版本,能夠捕獲這些異常。
None
。
下載時遇到的錯誤常常是臨時性的,好比服務器過載時返回的503 Service Unavailable
錯誤。對於此類錯誤,咱們能夠在短暫等待後嘗試從新下載,由於這個服務器問題如今可能已經解決。不過,咱們不須要對全部錯誤都嘗試從新下載。若是服務器返回的是404 Not Found
這種錯誤,則說明該網頁目前並不存在,再次嘗試一樣的請求通常也不會出現不一樣的結果。
互聯網工程任務組(Internet Engineering Task Force)定義了HTTP錯誤的完整列表,從中能夠了解到4xx
錯誤發生在請求存在問題時,而5xx
錯誤則發生在服務端存在問題時。因此,咱們只須要確保download
函數在發生5xx
錯誤時重試下載便可。下面是支持重試下載功能的新版本代碼。
download
函數遇到
5xx
錯誤碼時,將會遞歸調用函數自身進行重試。此外,該函數還增長了一個參數,用於設定重試下載的次數,其默認值爲兩次。咱們在這裏限制網頁下載的嘗試次數,是由於服務器錯誤可能暫時尚未恢復。想要測試該函數,能夠嘗試下載
http://httpstat.us/500
,該網址會始終返回
500
錯誤碼。
download
函數的行爲和預期一致,先嚐試下載網頁,在接收到
500
錯誤後,又進行了兩次重試才放棄。
默認狀況下,urllib
使用Python-urllib/``3.x
做爲用戶代理下載網頁內容,其中3.x
是環境當前所用Python的版本號。若是能使用可辨識的用戶代理則更好,這樣能夠避免咱們的網絡爬蟲碰到一些問題。此外,也許是由於曾經歷過質量不佳的Python網絡爬蟲形成的服務器過載,一些網站還會封禁這個默認的用戶代理。
所以,爲了使下載網站更加可靠,咱們須要控制用戶代理的設定。下面的代碼對download
函數進行了修改,設定了一個默認的用戶代理‘wswp’
(即Web Scraping with Python的首字母縮寫)。
meetup.com
,就可以看到一個合法的HTML了。咱們的下載函數能夠在後續代碼中獲得複用,該函數可以捕獲異常、在可能的狀況下重試網站以及設置用戶代理。
在第一個簡單的爬蟲中,咱們將使用示例網站robots.txt
文件中發現的網站地圖來下載全部網頁。爲了解析網站地圖,咱們將會使用一個簡單的正則表達式,從<loc>
標籤中提取出URL。
咱們須要更新代碼以處理編碼轉換,由於咱們目前的download
函數只是簡單地返回了字節。下面是該示例爬蟲的代碼。
download
方法所示,咱們必須更新字符編碼才能利用正則表達式處理網站響應。Python的
read
方法返回字節,而正則表達式指望的則是字符串。咱們的代碼依賴於網站維護者在響應頭中包含適當的字符編碼。若是沒有返回字符編碼頭部,咱們將會把它設置爲默認值UTF-8,並抱有最大的但願。固然,若是返回頭中的編碼不正確,或是編碼沒有設置而且也不是UTF-8的話,則會拋出錯誤。還有一些更復雜的方式用於猜想編碼(參見
https://pypi.python.org/pypi/chardet
),該方法很是容易實現。
到目前爲止,網站地圖爬蟲已經符合預期。不過正如前文所述,咱們沒法依靠Sitemap
文件提供每一個網頁的連接。下一節中,咱們將會介紹另外一個簡單的爬蟲,該爬蟲再也不依賴於Sitemap
文件。
本節中,咱們將利用網站結構的弱點,更加輕鬆地訪問全部內容。下面是一些示例國家(或地區)的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所示。
圖1.1
從圖1.1中能夠看出,網頁依然能夠加載成功,也就是說該方法是有用的。如今,咱們就能夠忽略頁面別名,只利用數據庫ID來下載全部國家(或地區)的頁面了。下面是使用了該技巧的代碼片斷。
在爬取網站時,遍歷ID是一個很便捷的方法,可是和網站地圖爬蟲同樣,這種方法也沒法保證始終可用。好比,一些網站會檢查頁面別名是否在URL中,若是不是,則會返回404 Not Found
錯誤。而另外一些網站則會使用非連續大數做爲ID,或是不使用數值做爲ID,此時遍歷就難以發揮其做用了。例如,Amazon使用ISBN做爲可用圖書的ID,這種編碼包含至少10位數字。使用ID對ISBN進行遍歷須要測試數十億次可能的組合,所以這種方法確定不是抓取該站內容最高效的方法。
正如你一直關注的那樣,你可能已經注意到一些TOO MANY REQUESTS
下載錯誤信息。如今無須擔憂它,咱們將會在1.5節的「高級功能」部分中介紹更多處理該類型錯誤的方法。
到目前爲止,咱們已經利用示例網站的結構特色實現了兩個簡單爬蟲,用於下載全部已發佈的國家(或地區)頁面。只要這兩種技術可用,就應當使用它們進行爬取,由於這兩種方法將須要下載的網頁數量降至最低。不過,對於另外一些網站,咱們須要讓爬蟲表現得更像普通用戶,跟蹤連接,訪問感興趣的內容。
經過跟蹤每一個連接的方式,咱們能夠很容易地下載整個網站的頁面。可是,這種方法可能會下載不少並不須要的網頁。例如,咱們想要從一個在線論壇中抓取用戶帳號詳情頁,那麼此時咱們只須要下載帳號頁,而不須要下載討論貼的頁面。本文使用的連接爬蟲將使用正則表達式來肯定應當下載哪些頁面。下面是這段代碼的初始版本。
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)/
這個簡單的正則表達式來匹配這兩類網頁。當爬蟲使用這些輸入參數運行時會發生什麼呢?你會獲得以下所示的下載錯誤。
/index/1
時,該連接只有網頁的路徑部分,而沒有協議和服務器部分,也就是說這是一個
相對連接。因爲瀏覽器知道你正在瀏覽哪一個網頁,而且可以採起必要的步驟處理這些連接,所以在瀏覽器瀏覽時,相對連接是可以正常工做的。可是,
urllib
並無上下文。爲了讓
urllib
可以定位網頁,咱們須要將連接轉換爲
絕對連接的形式,以便包含定位網頁的全部細節。如你所願,Python的
urllib
中有一個模塊能夠用來實現該功能,該模塊名爲
parse
。下面是
link_crawler
的改進版本,使用了
urljoin
方法來建立絕對路徑。
link_crawler
函數,具有了存儲已發現URL的功能,能夠避免重複下載。
本文摘自《用Python寫網絡爬蟲(第2版)》
《用Python寫網絡爬蟲》
史上首本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 執行JavaScript 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
京東預售
噹噹預售
今日互動
學會爬蟲,你最想作的第一件事兒是什麼?爲何?截止時間7月21日17時,留言+轉發本活動到朋友圈,小編將抽獎選出2名讀者贈送紙書2本,文末留言點贊最多的自動得到圖書1本。
點擊閱讀原文,購買《用Python寫網絡爬蟲(第2版)》