背景
雖然寫過很多爬蟲,近期卻瞞著寫一個采集器。一整套爬蟲的集合,踩坑不少,特別寫一文記錄下來。
語言的選擇
Python!
應為語言足夠靈活,而且又足夠多的庫選擇。項目之初我還考慮過使用erlang。erlang的多進程特性雖然很好,但是erlang在編碼處理,文本解析方面的能力太弱,寫代碼寫的十分痛苦。故棄之。據說golang可能會更好,但是我還沒對這語言深入研究,用到公司的項目上來,實在有些欠妥。
Request包
很多人用python寫爬蟲,可能會使用Scrapy這樣的框架,但是我覺得因為抓取這種事情,很多時候,往往是兩個程序員之間的對決。所以,我傾向于更靈活的使用一個Request包,然后自己各方面分析來構建請求包,達到抓取數據的目的。
selenium
不是所有的頁面都能通過構造請求包來獲取的,尤其是很多需要驗證的頁面。還有很多頁面的數據,需要通過一大串js運算才會顯示出來,這樣無疑增加了抓取的難度,但是兵來將擋,水來土掩。
這個時候借助測試人員常用的自動化測試工具selenium,模擬人的訪問,獲取到你想要的數據。當然selenium也是對python兼容的。
當然,模擬自動化測試的方式,難度大,性能差,不到萬不得已不出招。
項目結構

-
collector:
程序的主體repo: 公共模塊,將抓取和分析的代碼抽取出來,還要又對時間的運算類,和日志類,以及操作數據庫和消息隊列的類。
task: 任務模塊,任務要做的事即使確定什么時候執(zhí)行抓取,抓取的結果放到那里。
worker:工作者模塊,抓取數據和分析數據的模塊。
tests:同等的目下, 是測試用例
runtime: 目錄下是日志和錯誤數據的記錄。
run*.py: 這些每個抓取的入口。因為是多進程的方式,故而分成多個入口。不同入口,對應不同的抓取內容。
多進程
為什么使用多進程的形式呢?因為線程不好控制,我的每個抓取進程之下,不同的任務用到不同的線程。但是不同抓取內容,沒有耦合的東西,所以采取這樣進程的方式,好管理,想啟動就啟動,想關掉,kill掉進程就是了。
使用nohup命令在后臺執(zhí)行程序:
nohup python run_xxx.py > runtime/xxxx.out &
異常的處理
采集器程序,是要把外部資源轉化為內部資源。凡是依賴外部的情況,都要考慮異常的風險。比如我抓取的很多東西在境外,因為某些不可描述的原因,網絡服務一直很不穩(wěn)定。所以超時處理的是必須的,超時拋出異常,而這個異常是我們認為沒什么大不了的事情,所以沒有必要因為這個異常破壞程序的執(zhí)行,所以我們只要抓取到異常,就直接重新發(fā)起請求再來一次就是了。
當然,這樣的處理過于簡單除暴了,最好還是讓程序讓程序稍后發(fā)起請求,因為發(fā)生異常之后,我的程序會觸發(fā)一個事件,這個事件回去檢查最近數據的一致性。做到盡量讓程序來監(jiān)督程序。
總結
簡單總結一下,還有什么坑,我想到再補。