一看就明白的爬蟲入門講解:基礎理論篇

allowtransparency="true" frameborder="0" scrolling="no" src="http://hits.sinajs.cn/A1/weiboshare.html?url=http%3A%2F%2Fwww.csdn.net%2Farticle%2F2015-11-13%2F2826205&type=3&count=&appkey=&title=%E6%9C%AC%E6%96%87%E4%BD%9C%E8%80%85%E8%AF%B8%E8%91%9BIO%E5%88%9B%E5%A7%8B%E4%BA%BA%2FCEO%E5%AD%94%E6%B7%BC%E4%BB%8E%E5%9F%BA%E7%A1%80%E7%90%86%E8%AE%BA%E5%85%A5%E6%89%8B%EF%BC%8C%E8%AF%A6%E7%BB%86%E8%AE%B2%E8%A7%A3%E4%BA%86%E7%88%AC%E8%99%AB%E5%86%85%E5%AE%B9%EF%BC%8C%E5%88%86%E4%B8%BA%E5%85%AD%E4%B8%AA%E9%83%A8%E5%88%86%EF%BC%9A%E6%88%91%E4%BB%AC%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9B%E5%86%85%E5%AE%B9%E4%BB%8E%E4%BD%95%E8%80%8C%E6%9D%A5%EF%BC%9B%E4%BA%86%E8%A7%A3%E7%BD%91%E7%BB%9C%E8%AF%B7%E6%B1%82%EF%BC%9B%E4%B8%80%E4%BA%9B%E5%B8%B8%E8%A7%81%E7%9A%84%E9%99%90%E5%88%B6%E6%96%B9%E5%BC%8F%EF%BC%9B%E5%B0%9D%E8%AF%95%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98%E7%9A%84%E6%80%9D%E8%B7%AF%EF%BC%9B%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98%E7%9A%84%E5%8F%96%E8%88%8D%E3%80%82&pic=&ralateUid=&language=zh_cn&rnd=1447446676245" width="22" height="16">摘要:本文作者諸葛IO創始人/CEO孔淼從基礎理論入手,詳細講解了爬蟲內容,分爲六個部分:我們的目的是什麼;內容從何而來;瞭解網絡請求;一些常見的限制方式;嘗試解決問題的思路;效率問題的取捨。

CSDN移動將持續爲您優選移動開發的精華內容,共同探討移動開發的技術熱點話題,涵蓋移動應用、開發工具、移動遊戲及引擎、智能硬件、物聯網等方方面面。如果您想投稿、尋求《近匠》報道,或給文章挑錯,歡迎發送郵件至tangxy#csdn.net(請把#改成@)。 


關於爬蟲內容的分享,我會分成兩篇,六個部分來分享,分別是:

  1. 我們的目的是什麼
  2. 內容從何而來
  3. 瞭解網絡請求
  4. 一些常見的限制方式
  5. 嘗試解決問題的思路
  6. 效率問題的取捨

一、我們的目的是什麼

一般來講對我們而言,需要抓取的是某個網站或者某個應用的內容,提取有用的價值,內容一般分爲兩部分,非結構化的文本,或結構化的文本。

1. 關於非結構化的數據

1.1 HTML文本(包含JavaScript代碼)

HTML文本基本上是傳統爬蟲過程中最常見的,也就是大多數時候會遇到的情況,例如抓取一個網頁,得到的是HTML,然後需要解析一些常見的元素,提取一些關鍵的信息。HTML其實理應屬於結構化的文本組織,但是又因爲一般我們需要的關鍵信息並非直接可以得到,需要進行對HTML的解析查找,甚至一些字符串操作才能得到,所以還是歸類於非結構化的數據處理中。

常見解析方式如下:

  • CSS選擇器

現在的網頁樣式比較多,所以一般的網頁都會有一些CSS的定位,例如class,id等等,或者我們根據常見的節點路徑進行定位,例如騰訊首頁的財經部分。


這裏id就爲finance,我們用css選擇器,就是"#finance"就得到了財經這一塊區域的html,同理,可以根據特定的css選擇器可以獲取其他的內容。

  • XPATH

XPATH是一種頁面元素的路徑選擇方法,利用Chrome可以快速得到,如:


copy XPATH 就能得到——//*[@id="finance"]

  • 正則表達式

正則表達式,用標準正則解析,一般會把HTML當做普通文本,用指定格式匹配當相關文本,適合小片段文本,或者某一串字符,或者HTML包含javascript的代碼,無法用CSS選擇器或者XPATH。

  • 字符串分隔

同正則表達式,更爲偷懶的方法,不建議使用。

1.2 一段文本

例如一篇文章,或者一句話,我們的初衷是提取有效信息,所以如果是滯後處理,可以直接存儲,如果是需要實時提取有用信息,常見的處理方式如下:

  • 分詞

根據抓取的網站類型,使用不同詞庫,進行基本的分詞,然後變成詞頻統計,類似於向量的表示,詞爲方向,詞頻爲長度。

  • NLP

自然語言處理,進行語義分析,用結果表示,例如正負面等。

2. 關於結構化的數據

結構化的數據是最好處理,一般都是類似JSON格式的字符串,直接解析JSON數據就可以了,提取JSON的關鍵字段即可。

二、內容從何而來

過去我們常需要獲取的內容主要來源於網頁,一般來講,我們決定進行抓取的時候,都是網頁上可看到的內容,但是隨着這幾年移動互聯網的發展,我們也發現越來越多的內容會來源於移動App,所以爬蟲就不止侷限於一定要抓取解析網頁,還有就是模擬移動app的網絡請求進行抓取,所以這一部分我會分兩部分進行說明。

1 網頁內容

網頁內容一般就是指我們最終在網頁上看到的內容,但是這個過程其實並不是網頁的代碼裏面直接包含內容這麼簡單,所以對於很多新人而言,會遇到很多問題,比如:

明明在頁面用Chrome或者Firefox進行審查元素時能看到某個HTML標籤下包含內容,但是抓取的時候爲空。
很多內容一定要在頁面上點擊某個按鈕或者進行某個交互操作才能顯示出來。

所以對於很多新人的做法是用某個語言別人模擬瀏覽器操作的庫,其實就是調用本地瀏覽器或者是包含了一些執行JavaScript的引擎來進行模擬操作抓取數據,但是這種做法顯然對於想要大量抓取數據的情況下是效率非常低下,並且對於技術人員本身而言也相當於在用一個盒子,那麼對於這些內容到底是怎麼顯示在網頁上的呢?主要分爲以下幾種情況:

  • 網頁包含內容

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

  • JavaScript代碼加載內容

這種情況是由於雖然網頁顯示時,內容在HTML標籤裏面,但是其實是由於執行js代碼加到標籤裏面的,所以這個時候內容在js代碼裏面的,而js的執行是在瀏覽器端的操作,所以用程序去請求網頁地址的時候,得到的response是網頁代碼和js的代碼,所以自己在瀏覽器端能看到內容,解析時由於js未執行,肯定找到指定HTML標籤下內容肯定爲空,這個時候的處理辦法,一般來講主要是要找到包含內容的js代碼串,然後通過正則表達式獲得相應的內容,而不是解析HTML標籤。

  • Ajax異步請求

這種情況是現在很常見的,尤其是在內容以分頁形式顯示在網頁上,並且頁面無刷新,或者是對網頁進行某個交互操作後,得到內容。那我們該如何分析這些請求呢?這裏我以Chrome的操作爲例,進行說明:


所以當我們開始刷新頁面的時候就要開始跟蹤所有的請求,觀察數據到底是在哪一步加載進來的。然後當我們找到核心的異步請求的時候,就只用抓取這個異步請求就可以了,如果原始網頁沒有任何有用信息,也沒必要去抓取原始網頁了。

2 App內容

因爲現在移動應用越來越多,很多有用信息都在App裏面,另外解析非結構化文本和結構文本對比而言,結構化文本會簡單多了,不同去找內容,去過多分析解析,所有既有網站又有App的話,推薦抓取App,大多數情況下基本上只是一些JSON數據的API了。

那麼App的數據該如何抓取呢?通用的方法就是抓包,基本的做法就是電腦安裝抓包軟件,配置好端口,然後記下ip,手機端和電腦在同一個局域網裏面,然後在手機的網絡連接裏面設置好代理,這個時候打開App進行一些操作,如果有網絡數據請求,則都會被抓包軟件記下,就如上Chrome分析網絡請求一樣,你可以看到所有的請求情況,可以模擬請求操作。這裏Mac上我推薦軟件Charles,Windows推薦Fiddler2。

具體如何使用,之後我再做詳述,可能會涉及到HTTPS證書的問題。

三、瞭解網絡請求

剛剛一直在寬泛的提到一些我們需要找到請求,進行請求,對於請求只是一筆帶過,但請求是很重要的一部分,包括如何繞過限制,如何發送正確地數據,都需要對的請求,這裏就要詳細的展開說下請求,以及如何模擬請求。

我們常說爬蟲其實就是一堆的HTTP請求,找到待爬取的鏈接,不管是網頁鏈接還是App抓包得到的API鏈接,然後發送一個請求包,得到一個返回包(也有HTTP長連接,或者Streaming的情況,這裏不考慮),所以核心的幾個要素就是:

  1. URL
  2. 請求方法(POST, GET)
  3. 請求包headers
  4. 請求包內容
  5. 返回包headers

在用Chrome進行網絡請求捕獲或者用抓包工具分析請求時,最重要的是弄清楚URL,請求方法,然後headers裏面的字段,大多數出問題就出在headers裏面,最常限制的幾個字段就是User-Agent, Referer, Cookie 另外Base Auth也是在headers裏面加了Autheration的字段。

請求內容也就是post時需要發送的數據,一般都是將Key-Value進行urlencode。返回包headers大多數會被人忽視,可能只得到內容就可以了,但是其實很多時候,很多人會發現明明url,請求方法還有請求包的內容都對了,爲什麼沒有返回內容,或者發現請求被限制,其實這裏大概有兩個原因:

一個是返回包的內容是空的,但是在返回包的headers的字段裏面有個Location,這個Location字段就是告訴瀏覽器重定向,所以有時候代碼沒有自動跟蹤,自然就沒有內容了;
另外一個就是很多人會頭疼的Cookie問題,簡單說就是瀏覽器爲什麼知道你的請求合法的,例如已登錄等等,其實就是可能你之前某個請求的返回包的headers裏面有個字段叫Set-Cookie,Cookie存在本地,一旦設置後,除非過期,一般都會自動加在請求字段上,所以Set-Cookie裏面的內容就會告訴瀏覽器存多久,存的是什麼內容,在哪個路徑下有用,Cookie都是在指定域下,一般都不跨域,域就是你請求的鏈接host。

所以分析請求時,一定要注意前四個,在模擬時保持一致,同時觀察第五個返回時是不是有限制或者有重定向。

四、一些常見的限制方式

上述都是講的都是一些的基礎的知識,現在我就列一些比較常見的限制方式,如何突破這些限制抓取數據。

  • Basic Auth

一般會有用戶授權的限制,會在headers的Autheration字段裏要求加入;

  • Referer

通常是在訪問鏈接時,必須要帶上Referer字段,服務器會進行驗證,例如抓取京東的評論;

  • User-Agent

會要求真是的設備,如果不加會用編程語言包裏自有User-Agent,可以被辨別出來;

  • Cookie

一般在用戶登錄或者某些操作後,服務端會在返回包中包含Cookie信息要求瀏覽器設置Cookie,沒有Cookie會很容易被辨別出來是僞造請求;

也有本地通過JS,根據服務端返回的某個信息進行處理生成的加密信息,設置在Cookie裏面;

  • Gzip

請求headers裏面帶了gzip,返回有時候會是gzip壓縮,需要解壓;

  • JavaScript加密操作

一般都是在請求的數據包內容裏面會包含一些被javascript進行加密限制的信息,例如新浪微博會進行SHA1和RSA加密,之前是兩次SHA1加密,然後發送的密碼和用戶名都會被加密;

  • 其他字段

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

真實的請求過程中,其實不止上面某一種限制,可能是幾種限制組合在一次,比如如果是類似RSA加密的話,可能先請求服務器得到Cookie,然後再帶着Cookie去請求服務器拿到公鑰,然後再用js進行加密,再發送數據到服務器。所以弄清楚這其中的原理,並且耐心分析很重要。

五、嘗試解決問題的思路

首先大的地方,加入我們想抓取某個數據源,我們要知道大概有哪些路徑可以獲取到數據源,基本上無外乎三種:

  1. PC端網站;
  2. 針對移動設備響應式設計的網站(也就是很多人說的H5, 雖然不一定是H5);
  3. 移動App;

原則是能抓移動App的,最好抓移動App,如果有針對移動設備優化的網站,就抓針對移動設備優化的網站,最後考慮PC網站。因爲移動App基本都是API很簡單,而移動設備訪問優化的網站一般來講都是結構簡單清晰的HTML,而PC網站自然是最複雜的了;

針對PC端網站和移動網站的做法一樣,分析思路可以一起講,移動App單獨分析。

1 網站類型的分析

首先是網站類的,使用的工具就是Chrome,建議用Chrome的隱身模式,分析時不用頻繁清楚cookie,直接關閉窗口就可以了。

具體操作步驟如下:

  • 輸入網址後,先不要回車確認,右鍵選擇審查元素,然後點擊網絡,記得要勾上preserve log選項,因爲如果出現上面提到過的重定向跳轉,之前的請求全部都會被清掉,影響分析,尤其是重定向時還加上了Cookie;
  • 接下來觀察網絡請求列表,資源文件,例如css,圖片基本都可以忽略,第一個請求肯定就是該鏈接的內容本身,所以查看源碼,確認頁面上需要抓取的內容是不是在HTML標籤裏面,很簡單的方法,找到自己要找的內容,看到父節點,然後再看源代碼裏面該父節點裏面有沒有內容,如果沒有,那麼一定是異步請求,如果是非異步請求,直接抓該鏈接就可以了。

分析異步請求,按照網絡列表,略過資源文件,然後點擊各個請求,觀察是否在返回時包含想要的內容,有幾個方法:

  • 內容比較有特點,例如人的屬性信息,物品的價格,或者微博列表等內容,直接觀察可以判斷是不是該異步請求;
  • 知道異步加載的內容節點或者父節點的class或者id的名稱,找到js代碼,閱讀代碼得到異步請求;
  • 確認異步請求之後,就是要分析異步請求了,簡單的,直接請求異步請求,能得到數據,但是有時候異步請求會有限制,所以現在分析限制從何而來。

針對分析對請求的限制,思路是逆序方法。

  • 先找到最後一個得到內容的請求,然後觀察headers,先看post數據或者url的某個參數是不是都是已知數據,或者有意義數據,如果發現不確定的先帶上,只是更改某個關鍵字段,例如page,count看結果是不是會正常,如果不正常,比如多了個token,或者某個字段明顯被加密,例如用戶名密碼,那麼接下來就要看JS的代碼,看到底是哪個函數進行了加密,一般會是原生JS代碼加密,那麼看到代碼,直接加密就行,如果是類似RSA加密,那麼就要看公鑰是從何而來,如果是請求得到的,那麼就要往上分析請求,另外如果是發現請求headers裏面有陌生字段,或者有Cookie也要往上看請求,Cookie在哪一步設置的;
  • 接下來找到剛剛那個請求未知來源的信息,例如Cookie或者某個加密需要的公鑰等等,看看上面某個請求是不是已經包含,依次類推。

2 App的分析

然後是App類的,使用的工具是Charles,手機和電腦在一個局域網內,先用Charles配置好端口,然後手機設置代理,ip爲電腦的ip,端口爲設置的端口,然後如果手機上請求網絡內容時,Charles會顯示相應地請求,那麼就ok了,分析的大體邏輯基本一致,限制會相對少很多,但是也有幾種情況需要注意:

  • 加密,App有時候也有一些加密的字段,這個時候,一般來講都會進行反編譯進行分析,找到對應的代碼片段,逆推出加密方法;
  • gzip壓縮或者base64編碼,base64編碼的辨別度較高,有時候數據被gzip壓縮了,不過Charles都是有自動解密的;
  • https證書,有的https請求會驗證證書,Charles提供了證書,可以在官網找到,手機訪問,然後信任添加就可以。

六、效率問題的取捨

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

涉及到大規模的抓取,一定要有良好的爬蟲設計,一般很多開源的爬蟲框架也都是有限制的,因爲中間涉及到很多其他的問題,例如數據結構,重複抓取過濾的問題,當然最重要的是要把帶寬利用滿,所以分佈式抓取很重要,接下來我會有一篇專門講分佈式的爬蟲設計,分佈式最重要的就是中間消息通信,如果想要抓的越多越快,那麼對中間的消息系統的吞吐量要求也越高。

但是對於一些不太大規模的抓取就沒要用分佈式的一套,比較消耗時間,基本只要保證單機器的帶寬能夠利用滿就沒問題,所以做好併發就可以,另外對於數據結構也要有一定的控制,很多人寫程序,內存越寫越大,抓取越來越慢,可能存在的原因就包括,一個是用了內存存一些數據沒有進行釋放,第二個可能有一些hashset的判斷,最後判斷的效率越來越低,比如用bloomfilter替換就會優化很多。

(審校/唐小引)


作者簡介:

孔淼,90後,諸葛IO創始人/CEO,畢業於華中科技大學軟件工程專業。大學期間獲得全球最大學生技術創新比賽微軟創新杯兩項一等獎,騰訊校園之星大賽全國第二,全國大學生計算機設計大賽一等獎,HTML5 code jam武漢冠軍。曾受邀實習於創新工場,擔任李開復博士的技術主力,負責處理工場各部門以及李開復的技術需求。畢業後放棄保研以及各大公司offer,加入37degree團隊開始創業。在37degree期間,曾帶領團隊服務過CCTV、海爾、寶馬等知名企業。過去4年間,孔淼專注於對數據分析、數據挖掘領域的探究,並於去年起打造了新一代的數據服務平臺——諸葛IO。

第一時間掌握最新移動開發相關信息和技術,請關注mobilehub公衆微信號(ID: mobilehub)。

 


發佈了171 篇原創文章 · 獲贊 9 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章