1.爬蟲定義
爬蟲就是用計算機代替人工去獲取海量的web數(shù)據(jù)的程序。是獲取數(shù)據(jù)的一種方式酝润,也是數(shù)據(jù)分析的前提。
2.編寫一個合格的爬蟲程序
1)爬蟲程序目的不是攻擊網(wǎng)站,而是獲取開放的數(shù)據(jù)镶苞。但是由于爬蟲的程序特性,獲取資源速度過快鞠评,可能會導致服務器癱瘓茂蚓。因此爬取信息時需要盡量模仿人工獲取行為,所以發(fā)送多個請求之間盡量間隔一個合理的隨機時間剃幌。
2)有些網(wǎng)站對爬蟲程序做了一些防備聋涨,比如請求頭的驗證。解決起來很簡單负乡,在請求頭中加入一些客戶端信息(如:User-Agent)或者上下文信息(如:Referer)牍白。
3)有些信息需要登陸之后才能訪問。于是模擬登陸就成了爬蟲程序需要的基本功能敬鬓,也是實現(xiàn)起來較為復雜的淹朋。
常見的網(wǎng)站登陸校驗方式有兩種,一種基于cookie钉答,一種基于token础芍。
cookie與服務器端的session一同保證交互的狀態(tài),用于克服http請求的無狀態(tài)特性数尿。這種情況的第一步當然是尋找登陸接口仑性,該過程一般為手動尋找。通過向登陸接口提交賬號密碼右蹦,進行登陸诊杆,服務器端登陸校驗過后,會在session中記錄登錄信息何陆,所以只需要保留已驗證的cookie晨汹,每次請求通過攜帶cookie信息,就能獲得已登陸的權(quán)限贷盲。
不過模擬登陸實現(xiàn)起來并不簡單淘这,因為很多網(wǎng)站的登陸接口遠遠不止只輸入賬號密碼這么簡單。常見的防備有驗證碼巩剖,還有動態(tài)生成的一些認證字符串铝穷。這些都讓爬蟲程序的模擬登陸不能做到完全自動化。一些簡單的驗證碼也許能夠使用一些圖像識別函數(shù)庫進行自動解析佳魔。
不過遇到一些高級的驗證方式就可能非常困難了:
更別說一些奇葩的驗證碼曙聂,連手動驗證都有點小困難:
以上純屬驗證碼搞笑,主要還是想說明模擬登陸的困難鞠鲜。
4)頁面js的處理宁脊,有些數(shù)據(jù)可能需要執(zhí)行js代碼后才會顯示在頁面上断国,這就表示網(wǎng)頁源代碼中是沒有我們需要的數(shù)據(jù)的。比如常見的ajax請求朦佩,獲取到數(shù)據(jù)之后再利用js將數(shù)據(jù)插入頁面并思。
3.擴展性的思考
對于爬蟲程序,要做到有效语稠,就必須要專一宋彼。因為web網(wǎng)頁結(jié)構(gòu)多種多樣,數(shù)據(jù)在頁面上的分布也不盡相同仙畦∈涮椋可以說爬蟲程序要做到抽象是很困難的。
不過這也不代表無法得到一個擴展性好的設計慨畸。
只要將爬取規(guī)則常見的情況列舉出來莱坎,似乎就能夠得到一些共性。
比如寸士,webmagic中就將爬取規(guī)則抽象成了help url和target url檐什。前者是列表頁面的url,后者是數(shù)據(jù)實體的url弱卡。比如前者代表文章列表乃正,后者就是某個文章頁面。這樣的設計符合大多數(shù)情況婶博。
我們可以把最終要的數(shù)據(jù)分為三種瓮具。
1)一個頁面代表一個數(shù)據(jù)實體。
2)一個接口返回的json或者xml數(shù)據(jù)代表一個數(shù)據(jù)實體凡人。
3)一個數(shù)據(jù)實體的部分數(shù)據(jù)在一個頁面上名党,部分數(shù)據(jù)又來自ajax請求。
其中第三種是復雜的挠轴,因為需要通過不同的接口拼裝出一個數(shù)據(jù)實體传睹。而程序是難以自行發(fā)現(xiàn)這些接口的。
雖然不同網(wǎng)站對登陸的實現(xiàn)不同岸晦,但無非是提交賬號密碼和驗證數(shù)據(jù)給登陸接口欧啤。然后通過已認證的cookie或者token作為登陸憑證和服務器進行后續(xù)的交互。
難點是委煤,如何讓程序自行發(fā)現(xiàn)需要進行登陸堂油,或者之前的登陸已失效修档。服務器肯定是會告訴客戶端這些信息的碧绞,但是這里不同的網(wǎng)站實現(xiàn)又會不一樣,有的網(wǎng)站是直接跳轉(zhuǎn)至登陸頁面吱窝,而有的網(wǎng)站是返回一個錯誤碼讥邻,彈框確認之后再跳轉(zhuǎn)迫靖,或者有些設計不佳的網(wǎng)站,登陸失效后什么也不提示兴使,直接不返回任何數(shù)據(jù)系宜。
總的來說,要把一個爬蟲程序做好发魄,最好還是先做到專一盹牧,根據(jù)不同的網(wǎng)站設計不同的爬取規(guī)則,編寫不同的實現(xiàn)励幼,這樣雖然不易擴展汰寓,但實現(xiàn)起來要方便。等這般設計的系統(tǒng)穩(wěn)定之后苹粟,如果業(yè)務所需的數(shù)據(jù)來源不再變化有滑,再將已有的數(shù)據(jù)來源的通用部分進行抽象,再來考慮擴展性嵌削。