獨家|一文讀懂網絡爬蟲

獨家|一文讀懂網絡爬蟲

獨家|一文讀懂網絡爬蟲

前言

在當前數據爆發的時代,數據分析行業勢頭強勁,越來越多的人涉足數據分析領域。進入領域最想要的就是獲取大量的數據來為自己的分析提供支持,但是如何獲取互聯網中的有效信息?這就促進了“爬蟲”技術的飛速發展。

網絡爬蟲(又被稱為網頁蜘蛛,網絡機器人,在FOAF社區中間,更經常的稱為網頁追逐者),是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本。

傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定停止條件。聚焦爬蟲的工作流程較為複雜,需要根據一定的網頁分析算法過濾與主題無關的鏈接,保留有用的鏈接並將其放入等待抓取的URL隊列。然後,它將根據一定的搜索策略從隊列中選擇下一步要抓取的網頁URL,並重覆上述過程,直到達到系統的某一條件時停止。

另外,所有被爬蟲抓取的網頁將會被系統存貯,進行一定的分析、過濾,並建立索引,以便之後的查詢和檢索;對於聚焦爬蟲來說,這一過程所得到的分析結果還可能對以後的抓取過程給出反饋和指導。

筆者是爬蟲初學者,通過這篇綜述來記錄一下自己的心得體會。

以下為文章主要內容:

獨家|一文讀懂網絡爬蟲

1. 初見爬蟲

使用Python中的Requests第三方庫。在Requests的7個主要方法中,最常使用的就是get()方法,通過該方法構造一個向服務器請求資源的Request對象,結果返回一個包含服務器資源的額Response對象。通過Response對象則可以獲取請求的返回狀態、HTTP響應的字符串即URL對應的頁面內容、頁面的編碼方式以及頁面內容的二進制形式。

在瞭解get()方法之前我們先了解一下HTTP協議,通過對HTTP協議來理解我們訪問網頁這個過程到底都進行了哪些工作。

1.1 淺析HTTP協議

超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網絡協議。所有的www文件都必須遵守這個標準。HTTP協議主要有幾個特點:

  • 支持客戶/服務器模式

  • 簡單快捷:客服向服務器發出請求,只需要傳送請求方法和路徑。請求方法常用的有GET, HEAD, POST。每種方法規定了客戶與服務器聯繫的類型不同。由於HTTP協議簡單,使得HTTP服務器的程序規模小,因而通信速度快。

  • 靈活:HTTP允許傳輸任意類型的數據對象。

  • 無連接:無連接的含義是限制每次連接請求只處理一個請求。服務器處理完客戶的請求,收到客戶的應答後即斷開連接,這種方式可以節省傳輸時間。

  • 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事物處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大,另一方面,在服務器不需要先前信息時它的應答就較快。

下面通過一張圖我們來了解一下訪問網頁的過程都發生了什麼:

獨家|一文讀懂網絡爬蟲

1. 首先瀏覽器拿到網址之後先將主機名解析出來。如 http://www.baidu.com/index.html 則會將主機名www.baidu.com 解析出來。

2. 查找ip,根據主機名,會首先查找ip,首先查詢hosts文件,成功則返回對應的ip地址,如果沒有查詢到,則去DNS服務器查詢,成功就返回ip,否則會報告連接錯誤。

3. 發送http請求,瀏覽器會把自身相關信息與請求相關信息封裝成HTTP請求 消息發送給服務器。

4. 服務器處理請求,服務器讀取HTTP請求中的內容,在經過解析主機,解析站點名稱,解析訪問資源後,會查找相關資源,如果查找成功,則返回狀態碼200,失敗就會返回大名鼎鼎的404了,在服務器監測到請求不在的資源後,可以按照程序員設置的跳轉到別的頁面。所以有各種有個性的404錯誤頁面。

5. 服務器返回HTTP響應,瀏覽器得到返回數據後就可以提取數據,然後調用解析內核進行翻譯,最後顯示出頁面。之後瀏覽器會對其引用的文件比如圖片,css,js等文件不斷進行上述過程,直到所有文件都被下載下來之後,網頁就會顯示出來。

HTTP請求,http請求由三部分組成,分別是:請求行、消息報頭、請求正文。請求方法(所有方法全為大寫)有多種,各個方法的解釋如下:

  • GET 請求獲取Request-URI所標識的資源

  • POST 在Request-URI所標識的資源後附加新的數據

  • HEAD 請求獲取由Request-URI所標識的資源的響應消息報頭

  • PUT 請求服務器存儲一個資源,並用Request-URI作為其標識

  • DELETE 請求服務器刪除Request-URI所標識的資源

  • TRACE 請求服務器回送收到的請求信息,主要用於測試或診斷

  • CONNECT 保留將來使用

  • OPTIONS 請求查詢服務器的性能,或者查詢與資源相關的選項和需求

GET方法應用舉例:在瀏覽器的地址欄中輸入網址的方式訪問網頁時,瀏覽器採用GET方法向服務器獲取資源,eg:GET /form.html HTTP/1.1 (CRLF)

HTTP響應也是由三個部分組成,分別是:狀態行、消息報頭、響應正文。

狀態行格式如下:HTTP-Version Status-Code Reason-Phrase CRLF,其中,HTTP-Version表示服務器HTTP協議的版本;Status-Code表示服務器發回的響應狀態代碼;Reason-Phrase表示狀態代碼的文本描述。

狀態代碼有三位數字組成,第一個數字定義了響應的類別,且有五種可能取值:

  • 1xx:指示信息--表示請求已接收,繼續處理

  • 2xx:成功--表示請求已被成功接收、理解、接受

  • 3xx:重定向--要完成請求必須進行更進一步的操作

  • 4xx:客戶端錯誤--請求有語法錯誤或請求無法實現

  • 5xx:服務器端錯誤--服務器未能實現合法的請求

常見狀態代碼、狀態描述、說明:

200 OK //客戶端請求成功

400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解

401 Unauthorized //請求未經授權,這個狀態代碼必須和WWW-Authenticate報頭域一起使用

403 Forbidden //服務器收到請求,但是拒絕提供服務

404 Not Found //請求資源不存在,eg:輸入了錯誤的URL

500 Internal Server Error //服務器發生不可預期的錯誤

503 Server Unavailable //服務器當前不能處理客戶端的請求,一段時間後可能恢復正常。

eg:HTTP/1.1 200 OK (CRLF)

詳細的HTTP協議可以參考這篇文章:

http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html

前面我們瞭解了HTTP協議,那麼我們訪問網頁的過程,那麼網頁在是什麼樣子的。爬蟲眼中的網頁又是什麼樣子的。

網是靜態的,但爬蟲是動態的,所以爬蟲的基本思想就是沿著網頁(蜘蛛網的節點)上的鏈接的爬取有效信息。當然網頁也有動態(一般用PHP或ASP等寫成,例如用戶登陸界面就是動態網頁)的,但如果一張蛛網搖搖欲墜,蜘蛛會感到不那麼安穩,所以動態網頁的優先級一般會被搜索引擎排在靜態網頁的後面。

知道了爬蟲的基本思想,那麼具體如何操作呢?這得從網頁的基本概念說起。一個網頁有三大構成要素,分別是html文件、css文件和JavaScript文件。如果把一個網頁看做一棟房子,那麼html相當於房子外殼;css相當於地磚塗料,美化房子外觀內飾;JavaScript則相當於傢俱電器浴池等,增加房子的功能。從上述比喻可以看出,html才是網頁的根本,畢竟地磚顏料在市場上也有,傢俱電器都可以露天擺設,而房子外殼才是獨一無二的。

下面就是一個簡單網頁的例子:

獨家|一文讀懂網絡爬蟲

而在爬蟲眼裡,這個網頁是這樣的:

獨家|一文讀懂網絡爬蟲

因此網頁實質上就是超文本(hypertext),網頁上的所有內容都是在形如“<>...</>”這樣的標籤之內的。如果我們要蒐集網頁上的所有超鏈接,只需尋找所有標籤中前面是"href="的字符串,並查看提取出來的字符串是否以"http"(超文本轉換協議,https表示安全的http協議)開頭即可。如果超鏈接不以"http"開頭,那麼該鏈接很可能是網頁所在的本地文件或者ftp或smtp(文件或郵件轉換協議),應該過濾掉。

在Python中我們使用Requests庫中的方法來幫助我們實現對網頁的請求,從而達到實現爬蟲的過程。

1.2 Requests庫的7個主要方法:

獨家|一文讀懂網絡爬蟲

最常用的方法get用來實現一個簡單的小爬蟲,通過示例代碼展示:

獨家|一文讀懂網絡爬蟲

2. Robots協議

Robots協議(也稱為爬蟲協議、機器人協議等)的全稱是“網絡爬蟲排除標準”(Robots Exclusion Protocol),網站通過Robots協議告訴搜索引擎哪些頁面可以抓取,哪些頁面不能抓取。通過幾個小例子來解讀一下robots.txt中的內容,robots.txt默認放置於網站的根目錄小,對於一個沒有robots.txt文件的網站,默認是允許所有爬蟲獲取其網站內容的。

獨家|一文讀懂網絡爬蟲

我們對於robots協議的理解,如果是商業利益我們是必須要遵守robots協議內容,否則會承擔相應的法律責任。當只是個人玩轉網頁、練習則是建議遵守,提高自己編寫爬蟲的友好程度。

3. 網頁解析

BeautifulSoup嘗試化平淡為神奇,通過定位HTML標籤來格式化和組織複雜的網絡信息,用簡單易用的Python對象為我們展示XML結構信息。

BeautifulSoup是解析、遍歷、維護“標籤樹”的功能庫。

3.1 BeautifulSoup的解析器

獨家|一文讀懂網絡爬蟲

BeautifulSoup通過以上四種解析器來對我們獲取的網頁內容進行解析。使用官網的例子來看一下解析結果:

獨家|一文讀懂網絡爬蟲

首先獲取以上的一段HTML內容,我們通過BeautifulSoup解析之後,並且輸出解析後的結果來對比一下:

獨家|一文讀懂網絡爬蟲

通過解析的網頁內容,我們就可以使用BeautifulSoup中的方法來輕而易舉的獲得網頁中的主要信息:

獨家|一文讀懂網絡爬蟲

3.2 BeautifulSoup類的基本元素

獨家|一文讀懂網絡爬蟲

3.3 BeautifulSoup的遍歷功能

遍歷分為上行遍歷、下行遍歷、平行遍歷三種。

獨家|一文讀懂網絡爬蟲

  • 下行遍歷:

獨家|一文讀懂網絡爬蟲

  • 上行遍歷:

獨家|一文讀懂網絡爬蟲

  • 平行遍歷:

獨家|一文讀懂網絡爬蟲

4. 正則表達式

正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表通常被用來檢索、替換那些符合某個模式(規則)的文本。

筆者也是初學正則表達式,感覺自己不能簡潔清晰的講述正則表達式,建議參考網上的教程( http://deerchao.net/tutorials/regex/regex.htm#mission )圖文並茂,詳細講解了正則表達式。

通過掌握正則表示也可以幫助我們獲取網頁中的主要信息。

5. 爬蟲框架Scrapy

獨家|一文讀懂網絡爬蟲

Scrapy是Python開發的一個快速,高層次的屏幕抓取和web抓取框架,用於抓取web站點並從頁面中提取結構化的數據。Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試。

Scrapy吸引人的地方在於它是一個框架,任何人都可以根據需求方便的修改。它也提供了多種類型爬蟲的基類,如BaseSpider、sitemap爬蟲等,最新版本又提供了web2.0爬蟲的支持。

5.1 Scrapy爬蟲框架結構

獨家|一文讀懂網絡爬蟲

Engine: 控制所有模塊之間的數據流、根據條件觸發事件。

Downloader: 根據請求下載網頁

Scheduler: 對所有爬去請求進行調度管理

Spider: 解析Downloader返回的響應、產生爬取項、產生額外的爬去請求。

Item Pipelines: 以流水線方式處理Spider產生的爬取項、可能包括清理、檢驗和查重爬取項中的HTML數據、將數據存儲到數據庫。

5.2 數據流

1. 引擎打開一個網站(open a domain),找到處理該網站的Spider並向該spider請求第一個要爬取的URL(s)。

2. 引擎從Spider中獲取到第一個要爬取的URL並在調度器(Scheduler)以Request調度。

3. 引擎向調度器請求下一個要爬取的URL。

4. 調度器返回下一個要爬取的URL給引擎,引擎將URL通過下載中間件(請求(request)方向)轉發給下載器(Downloader)。

5. 一旦頁面下載完畢,下載器生成一個該頁面的Response,並將其通過下載中間件(返回(response)方向)發送給引擎。

6. 引擎從下載器中接收到Response並通過Spider中間件(輸入方向)發送給Spider處理。

7. Spider處理Response並返回爬取到的Item及(跟進的)新的Request給引擎。

8. 引擎將(Spider返回的)爬取到的Item給Item Pipeline,將(Spider返回的)Request給調度器。

9. (從第二步)重複直到調度器中沒有更多地request,引擎關閉該網站。

6. 分佈式爬蟲

6.1 多線程爬蟲

在爬取數據量小的情況下,我們使用的都是串行下載網頁的,只有前一次下載完成之後才會啟動新的下載。數據量小的情況下尚可應對。但面對大型網站就會顯得性能不足,如果我們可以同時下載多個網頁,那麼下載時間將會得到顯著改善。

我們將串行下載爬蟲擴展成並行下載。需要注意的是如果濫用這一功能,多線程爬蟲請求內容過快,可能會造成服務器過載,或是IP地址被封禁。為了避免這一問題,我們的爬蟲就要設置一個delay標識,用於設定請求同一域名時的最小時間間隔。

在Python中實現多線程是比較簡單的,Python中的thread模塊是比較底層的模塊,Python的threading模塊是對thread做了一些封裝,可以更加方便的被使用。

簡要的看一下thread模塊中含函數和常量:

獨家|一文讀懂網絡爬蟲

Thread中常用的函數和對象:

獨家|一文讀懂網絡爬蟲

一般來說,使用線程有兩種模式, 一種是創建線程要執行的函數, 把這個函數傳遞進Thread對象裡,讓它來執行. 另一種是直接從Thread繼承,創建一個新的class,把線程執行的代碼放到這個新的class裡。

實現多進程的代碼和例子參考:

http://www.jianshu.com/p/86b8e78c418a

6.2 多進程爬蟲

Python中的多線程其實並不是真正的多線程,並不能做到充分利用多核CPU資源。

如果想要充分利用,在python中大部分情況需要使用多進程,那麼這個包就叫做 multiprocessing。

藉助它,可以輕鬆完成從單進程到併發執行的轉換。multiprocessing支持子進程、通信和共享數據、執行不同形式的同步,提供了Process、Queue、Pipe、Lock等組件。

Process基本使用:

在multiprocessing中,每一個進程都用一個Process類來表示。首先看下它的API:

獨家|一文讀懂網絡爬蟲

  • target 表示調用對象,你可以傳入方法的名字

  • args 表示被調用對象的位置參數元組,比如target是函數a,他有兩個參數m,n,那麼args就傳入(m, n)即可

  • kwargs 表示調用對象的字典

  • name 是別名,相當於給這個進程取一個名字

  • group 分組,實際上不使用

我們先用一個實例來感受一下:

獨家|一文讀懂網絡爬蟲

最簡單的創建Process的過程如上所示,target傳入函數名,args是函數的參數,是元組的形式,如果只有一個參數,那就是長度為1的元組。

然後調用start()方法即可啟動多個進程了。

另外你還可以通過 cpu_count() 方法還有 active_children() 方法獲取當前機器的 CPU 核心數量以及得到目前所有的運行的進程。

通過一個實例來感受一下:

獨家|一文讀懂網絡爬蟲

運行結果:

獨家|一文讀懂網絡爬蟲

通過開啟多個進程實現爬蟲,會大大縮減爬取信息的速度。詳細介紹請參考:

http://cuiqingcai.com/3335.html

7. 異步網站數據採集

在收集網頁信息時我們會遇到,網頁的加載模型為瀑布流形式,頁面URL沒有改變,但依然可以加載出內容。這時候就需要我們分析網頁中JavaScript中的一些代碼,從中獲取我們所需要的數據。

面對使用JS渲染的頁面推薦使用PhantomJS,無界面,可腳本編程的WebKit瀏覽器。參考 : http://cuiqingcai.com/2577.html

Selenium一種自動化測試工具。可以方便實現Web界面測試。使用PhantomJS渲染解析JS,Selenium用來驅動以及寫與Python的對接,然後Python進行後期處理。參考: http://cuiqingcai.com/2599.html

8. 爬蟲的存儲

在剛開始接觸爬蟲的時候,我們習慣將小的爬蟲結果輸出在命令行中,看著命令行中一行行的數據顯得頗有成就感,但是隨著數據的增多,並且需要進行數據分析時,將數據打印到命令行就不是辦法了。為了可以遠程使用大部分網絡爬蟲,我們還是需要將收集的數據存儲起來。

8.1 媒體文件

媒體文件常見的有兩種存儲方式:只獲取URL鏈接,或者直接把源文件下載下來。但是推薦使用第一種方式。優點如下:

  • 爬蟲運行的更快,耗費的流量更少,因為只存儲鏈接,不需要下載文件。

  • 節省存儲空間,因為不需要存儲媒體文件。

  • 存儲URL的代碼更容易寫,也不需要實現文件下載代碼

  • 不下載文件能夠降低目標主機服務器的負載。

當然這樣做也存在一些缺點:

  • 內嵌在我們網頁中的外站鏈接被稱為盜鏈,使用這種鏈接會讓我們麻煩不斷,每個網站都會實施防盜鏈措施。

  • 因為你的鏈接文件在別人的服務器,所以我們的應用就要跟著別人的節奏運行了。

  • 盜鏈很容易改變,如果把盜鏈放在博客等地,被對方發現很可能被惡搞。或者是把URL存儲備用,等到用的時候發現鏈接已經過期了。

  • 在現實中網絡瀏覽器不僅可以訪問HTML頁面並切換頁面,它們也會下載訪問頁面上的所有資源。下載文件會讓我們的爬蟲看起來更像人在瀏覽頁面。

8.2 把數據存儲到CSV

CSV是存儲表格數據的常用文件格式。每行都用一個換行符分隔,列與列之間用逗號分隔。Python中的CSV庫可以非常簡單的修改CSV文件,也可以從零開始創建一個CSV文件:

獨家|一文讀懂網絡爬蟲

我們可以使用csv模塊提供的功能將爬蟲獲取的信息存入csv文件中。

8.3 MySQL

對於大量的爬蟲數據,並且在之後我們需要反覆用來篩選分析的數據,我們選擇存儲在數據庫中。

MySQL是目前最受歡迎的開源關係型數據庫管理系統,它是一種非常靈活、穩定、功能齊全的DBMS,許多頂級網站都在用它,YouTube、Twitter、Facebook等。

Python中沒有內置的MySQL支持工具,不過,有很多開源的庫可以用來與MySQL做交互,最為出名的就是PyMySQL。

獨家|一文讀懂網絡爬蟲

結合上述過程將爬蟲獲取到的數據存入數據庫中。

9. 爬蟲的常見技巧

9.1 模擬登錄

目前的網站多是採用cookie跟蹤用戶是否已經登錄的信息。一旦網站驗證了你的登錄權證,它就會保存在你瀏覽器的cookie中,裡面通常包含一個服務器生成的命令牌、登錄有效時限和狀態跟蹤信息。網站會把這個cookie當作信息驗證的證據,在我們瀏覽網站的每個頁面時出示給服務器。

通過Chrome等瀏覽器自帶的開發者工具,我們從Network中獲取請求網頁的頭部和表單,在Header中我們就可以查看cookie中存儲的登錄信息,我們可以通過Scrapy設置請求網頁的頭部信息,並將cookie存儲在本地,來實現模擬登陸的效果。詳細的操作可以查看博客:http://www.jianshu.com /p/b7f41df6202d

9.2 網頁驗證碼

簡單的說,驗證碼就是一張圖片,圖片上有字符串。網站是如何實現的呢?有WEB基礎的人可能會知道,每個瀏覽器基本都有cookie,作為這次回話的唯一標示。每次訪問網站,瀏覽器都會把這個cookie發送給服務器。驗證碼就是和這個cookie綁定到一起的。如何理解呢?舉個例子,現在有網站W,有A和B兩個人,同時訪問W,W給A返回的驗證碼是X,給B返回的驗證碼是Y,這兩個驗證碼都是正確的,但是如果A輸入了B的驗證碼,肯定驗證不通過。那服務器是怎麼區分A和B呢,就是用到的cookie。再舉個例子,有些網站你登錄一次之後,下次繼續訪問可能就自動登陸了,也是用cookie來標示唯一身份的,如果清除了cookie也就無法自動登陸了。

對於一些簡單的驗證碼我們可以通過機器識別,但是對於一些人眼都很難識別的驗證碼就只能尋找更加複雜的技術了。簡單的驗證碼識別過程就是對驗證碼圖片的一個處理過程。

  • 灰度圖轉換,可以結合opencv中的imread方法。

  • 圖像去噪(均值濾波器、高斯濾波器等等)。

  • 圖像二值化(這個過程中驗證碼中的字符串已經成為黑色的,底色為白色)。

    獨家|一文讀懂網絡爬蟲

  • 使用圖像識別方式,識別圖中的字符串達到識別驗證碼的目的。

推薦閱讀:

http://www.jianshu.com/p/dd699561671b

http://www.cnblogs.com/hearzeus/p/5166299.html(上篇)

http://www.cnblogs.com/hearzeus/p/5226546.html(下篇)

9.3 爬蟲代理池

由於筆者是個爬蟲初學者也沒有用到過這麼複雜的技術,不過筆者在爬蟲的過程中的確是體會了被封IP地址的痛苦。所以推薦大家有精力的可以來學習並完成一個。

推薦閱讀:

https://www.zhihu.com/question/47464143

10. 防爬蟲

由於暴力爬蟲會對網站的服務器產生很大的壓力,所以各個網站對爬蟲都有限制,大多數網站會定義robots.txt.文件可以讓爬蟲瞭解該網站的限制。限制是作為建議給出。但是爬蟲前檢查該文件可以最小化我們的爬蟲被封禁的可能。

一篇關於反爬蟲的文章: https://segmentfault.com/a/ 1190000005840672 (來自攜程技術中心)

11. 學習資料

推薦書籍:

  • 《Python網絡數據採集》 陶俊傑、陳小莉 譯

獨家|一文讀懂網絡爬蟲

  • 《用Python寫網絡爬蟲》 李斌 譯

獨家|一文讀懂網絡爬蟲

推薦博客:

  • 崔慶才得個人博客,有大量關於爬蟲的文章,而且講解的比較細緻。

    http://cuiqingcai.com/

  • 數據挖掘與入門實戰微信公眾號分享的一篇文章,《Python開源爬蟲項目代碼:抓取淘寶、京東、QQ、知網數據》,有十九個開源的爬蟲項目,可以給大家提供參考。https://github.com/hlpassion/blog/issues/6

推薦視頻:

  • 網易雲課堂,例子清晰,可以跟做。

    http://study.163.com/course/introduction.htm?courseId=1002794001#/courseDetail

  • Python網絡爬蟲與信息提取

    http://www.icourse163.org/course/BIT-1001870001

  • 更多精彩請關注清華-青島數據科學研究院微信官方公眾平臺“THU數據派”

相關推薦

推薦中...