背景
雖然寫過很多爬蟲豺妓,近期卻瞞著寫一個(gè)采集器惜互。一整套爬蟲的集合布讹,踩坑不少,特別寫一文記錄下來训堆。
語言的選擇
Python描验!
應(yīng)為語言足夠靈活,而且又足夠多的庫選擇坑鱼。項(xiàng)目之初我還考慮過使用erlang膘流。erlang的多進(jìn)程特性雖然很好,但是erlang在編碼處理姑躲,文本解析方面的能力太弱睡扬,寫代碼寫的十分痛苦。故棄之黍析。據(jù)說golang可能會(huì)更好,但是我還沒對(duì)這語言深入研究屎开,用到公司的項(xiàng)目上來阐枣,實(shí)在有些欠妥。
Request包
很多人用python寫爬蟲奄抽,可能會(huì)使用Scrapy這樣的框架蔼两,但是我覺得因?yàn)樽ト∵@種事情,很多時(shí)候逞度,往往是兩個(gè)程序員之間的對(duì)決额划。所以,我傾向于更靈活的使用一個(gè)Request包档泽,然后自己各方面分析來構(gòu)建請(qǐng)求包俊戳,達(dá)到抓取數(shù)據(jù)的目的。
selenium
不是所有的頁面都能通過構(gòu)造請(qǐng)求包來獲取的馆匿,尤其是很多需要驗(yàn)證的頁面抑胎。還有很多頁面的數(shù)據(jù),需要通過一大串js運(yùn)算才會(huì)顯示出來渐北,這樣無疑增加了抓取的難度阿逃,但是兵來將擋,水來土掩赃蛛。
這個(gè)時(shí)候借助測(cè)試人員常用的自動(dòng)化測(cè)試工具selenium恃锉,模擬人的訪問,獲取到你想要的數(shù)據(jù)呕臂。當(dāng)然selenium也是對(duì)python兼容的破托。
當(dāng)然,模擬自動(dòng)化測(cè)試的方式诵闭,難度大炼团,性能差澎嚣,不到萬不得已不出招。
項(xiàng)目結(jié)構(gòu)
-
collector:
程序的主體repo: 公共模塊瘟芝,將抓取和分析的代碼抽取出來易桃,還要又對(duì)時(shí)間的運(yùn)算類,和日志類锌俱,以及操作數(shù)據(jù)庫和消息隊(duì)列的類晤郑。
task: 任務(wù)模塊,任務(wù)要做的事即使確定什么時(shí)候執(zhí)行抓取贸宏,抓取的結(jié)果放到那里造寝。
worker:工作者模塊,抓取數(shù)據(jù)和分析數(shù)據(jù)的模塊吭练。
tests:同等的目下诫龙, 是測(cè)試用例
runtime: 目錄下是日志和錯(cuò)誤數(shù)據(jù)的記錄。
run*.py: 這些每個(gè)抓取的入口鲫咽。因?yàn)槭嵌噙M(jìn)程的方式签赃,故而分成多個(gè)入口。不同入口分尸,對(duì)應(yīng)不同的抓取內(nèi)容锦聊。
多進(jìn)程
為什么使用多進(jìn)程的形式呢?因?yàn)榫€程不好控制箩绍,我的每個(gè)抓取進(jìn)程之下孔庭,不同的任務(wù)用到不同的線程。但是不同抓取內(nèi)容材蛛,沒有耦合的東西圆到,所以采取這樣進(jìn)程的方式,好管理仰税,想啟動(dòng)就啟動(dòng)构资,想關(guān)掉,kill掉進(jìn)程就是了陨簇。
使用nohup命令在后臺(tái)執(zhí)行程序:
nohup python run_xxx.py > runtime/xxxx.out &
異常的處理
采集器程序吐绵,是要把外部資源轉(zhuǎn)化為內(nèi)部資源。凡是依賴外部的情況河绽,都要考慮異常的風(fēng)險(xiǎn)己单。比如我抓取的很多東西在境外,因?yàn)槟承?strong>不可描述的原因耙饰,網(wǎng)絡(luò)服務(wù)一直很不穩(wěn)定纹笼。所以超時(shí)處理的是必須的,超時(shí)拋出異常苟跪,而這個(gè)異常是我們認(rèn)為沒什么大不了的事情廷痘,所以沒有必要因?yàn)檫@個(gè)異常破壞程序的執(zhí)行蔓涧,所以我們只要抓取到異常,就直接重新發(fā)起請(qǐng)求再來一次就是了笋额。
當(dāng)然元暴,這樣的處理過于簡單除暴了,最好還是讓程序讓程序稍后發(fā)起請(qǐng)求兄猩,因?yàn)榘l(fā)生異常之后茉盏,我的程序會(huì)觸發(fā)一個(gè)事件,這個(gè)事件回去檢查最近數(shù)據(jù)的一致性枢冤。做到盡量讓程序來監(jiān)督程序鸠姨。
總結(jié)
簡單總結(jié)一下,還有什么坑淹真,我想到再補(bǔ)讶迁。