當前位置:
首頁 > 新聞 > 一篇文章了解爬蟲技術現狀

一篇文章了解爬蟲技術現狀

需求

萬維網上有著無數的網頁,包含著海量的信息,無孔不入、森羅萬象。但很多時候,無論出於數據分析或產品需求,我們需要從某些網站,提取出我們感興趣、有價值的內容,但是縱然是進化到21世紀的人類,依然只有兩隻手,一雙眼,不可能去每一個網頁去點去看,然後再複製粘貼。所以我們需要一種能自動獲取網頁內容並可以按照指定規則提取相應內容的程序,這就是爬蟲。

原理

傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定停止條件。

聚焦爬蟲的工作流程較為複雜,需要根據一定的網頁分析演算法過濾與主題無關的鏈接,保留有用的鏈接並將其放入等待抓取的URL隊列。然後,它將根據一定的搜索策略從隊列中選擇下一步要抓取的網頁URL,並重複上述過程,直到達到系統的某一條件時停止。

另外,所有被爬蟲抓取的網頁將會被系統存貯,進行一定的分析、過濾,並建立索引,以便之後的查詢和檢索;所以一個完整的爬蟲一般會包含如下三個模塊:

網路請求模塊

1. 爬取流程控制模塊

2. 內容分析提取模塊

3. 網路請求

我們常說爬蟲其實就是一堆的http(s)請求,找到待爬取的鏈接,然後發送一個請求包,得到一個返回包,當然,也有HTTP長連接(keep-alive)或h5中基於stream的websocket協議,這裡暫不考慮,所以核心的幾個要素就是:

1. url

2. 請求header、body

3. 響應herder、內容

URL

爬蟲開始運行時需要一個初始url,然後會根據爬取到的html文章,解析裡面的鏈接,然後繼續爬取,這就像一棵多叉樹,從根節點開始,每走一步,就會產生新的節點。為了使爬蟲能夠結束,一般都會指定一個爬取深度(Depth)。

Http請求

http請求信息由請求方法(method)、請求頭(headers)、請求正文(body)三部分組成。由於method一般是header中的第一行,也可以說請求頭中包含請求方法,下面是chrome訪問請求頭的一部分:

GET / HTTP/1.1Connection:Keep-AliveHost:gsw.iguoxue.org User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36Accept-Encoding:gzip, deflate, sdch, br

本文不會解釋各個欄位的意思,詳細的解釋請移步w3c Http Header Field Definitions 。 對於爬蟲需要注意的是請求方法是post時,需要將請求的參數先進行urlencode後再發送,後台收到請求信息後可能會做一些校驗,這可能會影響到爬取,相關的header欄位如下:

Basic Auth

這是一種古老的、不安全的用戶驗證方式,一般會有用戶授權的限制,會在headers的Autheration欄位里要求加入用戶名密碼(明文),如果驗證失敗則請求就會失敗,現在這種認證方式正在被淘汰。

Referer

鏈接的來源,通常在訪問鏈接時,都要帶上Referer欄位,伺服器會進行來源驗證,後台通常會用此欄位作為防盜鏈的依據。

User-Agent

後台通常會通過此欄位判斷用戶設備類型、系統以及瀏覽器的型號版本。有些編程語言包里網路請求會自定義User-Agent,可以被辨別出來,爬蟲中可以設置為瀏覽器的ua。

Cookie

一般在用戶登錄或者某些操作後,服務端會在返回包中包含Cookie信息要求瀏覽器設置Cookie,沒有Cookie會很容易被辨別出來是偽造請求;也有本地通過JS,根據服務端返回的某個信息進行處理生成的加密信息,設置在Cookie裡面;

JavaScript加密操作

在進行敏感數據傳輸時,一般都會通過javascript進行加密,例如qq空間就會對用戶登陸密碼進行RSA加密後再發送給伺服器,因此,爬蟲在模擬登陸時需要自己去請求公鑰,然後加密。

自定義欄位

因為http的headers可以自定義地段,所以第三方可能會加入了一些自定義的欄位名稱或者欄位值,這也是需要注意的。

流程控制

所謂爬取流程,就是按照什麼樣的規則順序去爬。在爬取任務不大的情況下,爬取的流程控制不會太麻煩,很多爬取框架都已經幫你做了如scrapy,只需要自己實現解析的代碼。

但在爬取一些大型網站時,例如全網抓取京東的評論,微博所有人的信息,關注關係等等,這種上十億到百億次設置千億次的請求必須考慮效率,否則一天只有86400秒,那麼一秒鐘要抓100次,一天也才8640w次請求,也需要100多天才能到達十億級別的請求量。

涉及到大規模的抓取,一定要有良好的爬蟲設計,一般很多開源的爬蟲框架也都是有限制的,因為中間涉及到很多其他的問題,例如數據結構,重複抓取過濾的問題,當然最重要的是要把帶寬利用滿,所以分布式抓取很重要,這時流程控制就會很重要。

分布式最重要的就是多台機器不同線程的調度和配合,通常會共享一個url隊列,然後各個線程通過消息通信,如果想要抓的越多越快,那麼對中間的消息系統的吞吐量要求也越高。

現在也有一些開源的分布式爬取框架如scrapy-redis就是一個重寫了scrapy的調度模塊、隊列、管道的包,redis資料庫是用來在分布式中做請求隊列共享,scrapyd是用來部署scrapy的,scrapyd-api用來啟動獲取數據。

內容分析提取

請求headers的Accept-Encoding欄位表示瀏覽器告訴伺服器自己支持的壓縮演算法(目前最多的是gzip),如果伺服器開啟了壓縮,返回時會對響應體進行壓縮,爬蟲需要自己解壓;

過去我們常需要獲取的內容主要來源於網頁html文檔本身,也就是說,我們決定進行抓取的時候,都是html中包含的內容,但是隨著這幾年web技術飛速的發展,動態網頁越來越多,尤其是移動端,大量的SPA應用,這些網站中大量的使用了ajax技術。

我們在瀏覽器中看到的網頁已不全是html文檔說包含的,很多都是通過javascript動態生成的,一般來說,我們最終眼裡看到的網頁包括以下三種:

Html文檔本身包含內容

這種情況是最容易解決的,一般來講基本上是靜態網頁已經寫死的內容,或者動態網頁,採用模板渲染,瀏覽器獲取到HTML的時候已經是包含所有的關鍵信息,所以直接在網頁上看到的內容都可以通過特定的HTML標籤得到。這種情況解析也是很簡單的,一般的方法有一下幾種:

1. CSS選擇器

2. XPATH(這個值得學習一下)

3. 正則表達式或普通字元串查找

4. JavaScript代碼載入內容

一般來說有兩種情況:

A. 一種情況是在請求到html文檔時,網頁的數據在js代碼中,而並非在html標籤中,之所以我們看到的網頁是正常的,那是因為,其實是由於執行js代碼動態添加到標籤裡面的,所以這個時候內容在js代碼裡面的,而js的執行是在瀏覽器端的操作,所以用程序去請求網頁地址的時候,得到的response是網頁代碼和js的代碼,所以自己在瀏覽器端能看到內容,解析時由於js未執行,肯定找到指定HTML標籤下內容肯定為空,如百度的主頁就是這種,這個時候的處理辦法,一般來講主要是要找到包含內容的js代碼串,然後通過正則表達式獲得相應的內容,而不是解析HTML標籤。

B. 另一種情況是在和用戶交互時,JavaScript可能會動態生成一些dom,如點擊某個按鈕彈了一個對話框等;對於這種情況,一般這些內容都是一些用戶提示相關的內容,沒什麼價值,如果確實需要,可以分析一下js執行邏輯,但這樣的情況很少。

Ajax/Fetch非同步請求

這種情況是現在很常見的,尤其是在內容以分頁形式顯示在網頁上,並且頁面無刷新,或者是對網頁進行某個交互操作後,得到內容。對於這種頁面,分析的時候我們要跟蹤所有的請求,觀察數據到底是在哪一步載入進來的。然後當我們找到核心的非同步請求的時候,就只需抓取這個非同步請求就可以了,如果原始網頁沒有任何有用信息,也沒必要去抓取原始網頁了。

爬蟲技術的現狀

語言

理論上來說,任何支持網路通信的語言都是可以寫爬蟲的,爬蟲本身雖然語言關係不大,但是,總有相對順手、簡單的。目前來說,大多數爬蟲是用後台腳本類語言寫的,其中python無疑是用的最多最廣的,並且頁誕生了很多優秀的庫和框架,如scrapy、BeautifulSoup 、pyquery、Mechanize等。

但是一般來說,搜索引擎的爬蟲對爬蟲的效率要求更高,會選用c++、java、go(適合高並發),詳情排名前50的開源Web爬蟲用於數據挖掘。

我在大學時代就用c++實現了一個多線程的框架,但是發現和python實現的爬蟲效率提升並不明顯,原因是,對於簡單爬蟲,瓶頸在於數據分析及提取,而網路效率和語言關係並不大。

值得一提的是,在近幾年node發展非常快, 使得javascript遍地開花,有些人也開始嘗試用node做爬蟲,但是,這其實和其它後台腳本語言沒什麼區別,也不如python簡單, 因為你依舊不能在node里發起ajax請求,不能執行原網頁的dom。因為node的javascript執行環境和瀏覽器的執行環境並不相同。

那麼,難道就真的不能像在瀏覽器中一樣用js寫爬蟲,用jquery提取內容嗎?想法很大膽,我們暫且擱置。

運行環境

爬蟲本身不區分到底是運行在windows還是Linux,又或是OSX,但從業務角度講,我們把運行在服務端(後台)的,稱之為後台爬蟲。而現在,幾乎所有的爬蟲都是後台爬蟲。

後台爬蟲的三大問題

後台爬蟲在大行其道的時候,也有著些許棘手的、到目前也沒有什麼好的解決方案問題,而歸根結底,這些問題的根本原因是由於後台爬蟲的先天不足導致,在正式討論之前,我們先思考一個問題,「爬蟲和瀏覽器有什麼異同?」

相同點

本質上都是通過http/https協議請求互聯網數據

不同點

爬蟲一般為自動化程序,無需用用戶交互,而瀏覽器不是;

運行場景不同;瀏覽器運行在客戶端,而爬蟲一般都跑在服務端;

能力不同;瀏覽器包含渲染引擎、javascript虛擬機,而爬蟲一般都不具備這兩者。

了解了這些,我們再來看看後檯面臨的問題:

問題一:交互問題

有些網頁往往需要和用戶進行一些交互,進而才能走到下一步,比如輸入一個驗證碼,拖動一個滑塊,選幾個漢字。網站之所以這麼做,很多時候都是為了驗證訪問者到底是人還是機器。

而爬蟲程序遇到這種情況很難處理,傳統的簡單圖片驗證碼可以通過圖形處理演算法讀出內容,但是隨著各種各樣,花樣百出,人神共憤的、變態的驗證碼越來越多(尤其是買火車票時,分分鐘都想爆粗口),這個問題就越來越嚴重。

問題二:Javascript 解析問題

如前文所述,javascript可以動態生成dom。目前大多數網頁屬於動態網頁(內容由javascript動態填充),尤其是在移動端,SPA/PWA應用越來越流行,網頁中大多數有用的數據都是通過ajax/fetch動態獲取後然後再由js填充到網頁dom樹中,單純的html靜態頁面中有用的數據很少。

目前主要應對的方案就是對於js ajax/fetch請求直接請求ajax/fetch的url ,但是還有一些ajax的請求參數會依賴一段javascript動態生成,比如一個請求簽名,再比如用戶登陸時對密碼的加密等等,如果一昧的去用後台腳本去干javascript本來做的事,這就要清楚的理解原網頁代碼邏輯,而這不僅非常麻煩,而且會使你的爬取代碼異常龐大臃腫。

但是,更致命的是,有些javascript可以做的事爬蟲程序是很難甚至是不能模仿的,比如有些網站使用拖動滑塊到某個位置的驗證碼機制,這就很難再爬蟲中去模仿。

其實,總結一些,這些弊端歸根結底,是因為爬蟲程序並非是瀏覽器,沒有javascript解析引擎所致。針對這個問題,目前主要的應對策略就是在爬蟲中引入Javascript 引擎,如PhantomJS,但是又有著明顯的弊端,如伺服器同時有多個爬取任務時,資源佔用太大。

還有就是,這些無窗口的javascript引擎很多時候使用起來並不能像在瀏覽器環境中一樣,頁面內部發生跳轉時,會導致流程很難控制。

問題三:IP限制

這是目前對後台爬蟲中最致命的。網站的防火牆會對某個固定ip在某段時間內請求的次數做限制,如果沒有超過上線則正常返回數據,超過了,則拒絕請求,如qq郵箱。

值得說明的是,ip限制有時並非是專門為了針對爬蟲的,而大多數時候是出於網站安全原因針對DOS攻擊的防禦措施。後台爬取時機器和ip有限,很容易達到上線而導致請求被拒絕。目前主要的應對方案是使用代理,這樣一來ip的數量就會多一些,但代理ip依然有限,對於這個問題,根本不可能徹底解決。

作者:lazydu

原文地址:

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

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

Pwn2Own2017專題:VMWARE UAF漏洞分析
愛奇藝優酷等18家視頻網站遭破解,會員視頻可免費觀看
屢禁不止:一個敢於將自己注入到殺毒軟體中的鬥士
Windows 日誌攻防之攻擊篇
愛奇藝等18家視頻網站遭破解,會員視頻可免費觀看

TAG:嘶吼RoarTalk |

您可能感興趣

一篇文章告訴你康熙來了綜藝咖的現狀
硬核解讀 一文讀懂隱私技術現狀
葯神來了?一文了解人工智慧藥物研發現狀
深度:一篇文章即可了解何為人工智慧及其發展現狀
一文了解我國自閉症康復現狀
一文看懂風電葉片的發展現狀
一文看懂中國集成電路材料現狀
一文看懂國產半導體材料現狀
一文看懂金融科技行業的現狀和未來
一文剖析區塊鏈現狀:叢林法則下的勝者
想了解手術機器人的發展現狀及專利布局情況?看這裡
單片異質集成技術研究現狀與進展
區塊鏈技術如何改變版權的現狀?
帶你了解亨廷頓舞蹈症研究現狀
從技術到產品,搜狗為我們解讀了神經機器翻譯的現狀
量產在即 固態電池技術發展現狀解讀
鋰離子電池技術發展現狀
一文讀懂分散式計算現狀與未來!
「圖正」——生物識別技術的現狀與未來
加固技術研究現狀