爬虫技术经历
1. 前言
爬蟲,這個詞很多朋友第一次聽到,第一感覺應該是各種小蟲子,應該不會和某種計算機技術聯系在一起。我第一次聽到這個詞,就是這樣一個感覺。但是當這個這個詞前面加了網絡二字時,瞬間勾起了我的興趣,當然也帶來了疑問。比如,網絡爬蟲是什么?有什么用?后來帶著強烈的興趣和疑問,查詢了很多資料,以求搞清除我的疑問。當我的疑問被解決的解決之后,懷著對爬蟲技術崇敬的心情做了一個決定,我要實現一個屬于自己的爬蟲程序。在我做這個決定的時候,時間節點是大三上學期期末。后來,過完寒假,到了大三下學期。我在大三下全學期用了3個月的時間,設計并實現了自己的爬蟲,并且花了5天的間用自己寫的爬蟲采集了100萬個網頁。這是我第一次與爬蟲技術親密接觸,總體感覺良好,學到了很多東西。到了大四上學期的期末,到了論文選題的時候了,我選了一個關于全文搜索引擎的論文題目,論文對應的程序由爬蟲和搜索兩個模塊組成。其中爬蟲直接用的開源實現?WebMagic,不過由于 WebMagic 不符合我的需求,所以我對 WebMagic 源碼進行了一定的改動,以保證爬蟲按照我的要求來執行任務。這是我第二次接觸爬蟲技術,當時感覺也不錯,改了別人的源碼,并且新加了一些新東西。改造完別人的爬蟲不久之后,就畢業了,大學生活也結束了。
以上,是我大學時候所接觸過的爬蟲技術。當我參加工作后,我所在的公司也有爬蟲,我也需要經常使用。所以從大三下開始接觸爬蟲到現在,算起來也有兩年半的時間了。這兩年多來,從大三開始自己寫爬蟲,大四改造別人的爬蟲,到現在用公司的爬蟲。我在爬蟲方面多多少少還是積累了一些經驗,也有一點感觸吧。看著自己以前寫的爬蟲的截圖,還是蠻感嘆的,時間過得真快啊。所以本篇文章我將把我這兩年多使用爬蟲的經歷寫出來,不過僅僅是記事,不會介紹爬蟲相關的原理。接下來我會按照時間順序依次敘述我的爬蟲經歷,好了,開始吧。
?2. 偶遇爬蟲
我在大三上學期期末的時候,開始在自學 Python。當時感覺 Python 還是比較容易的學的,但是通過看書學習的話,基本上看完就忘。對此,我也是頗為苦惱。于是后來總結原因,覺得是自己代碼寫的太少,以至于記不住語法。所以就尋思著寫一個稍微復雜的 Python 程序,這樣才能熟悉 Python。于是乎上網找練手項目,找了一圈,多數人都是推薦用 Python 寫爬蟲。但當時覺得爬蟲技術很復雜,所以內心還是比較拒絕的,不過既然大家都建議用 Python 寫爬蟲,那就硬著頭皮上吧。于是,在一個風高月黑的夜晚,入坑了。
在我開始準備寫爬蟲的時候,腦子真是一片空白。在此之前,我從來沒接觸過爬蟲相關的技術,也沒用過爬蟲框架。在準備階段,我查了不少資料,也寫了很多小例子。準備工作結束后,我對爬蟲相關的原理有了較為清晰的認識了,對 Python 的網絡相關的庫也相對熟練了很多。于是很有自信的開始規劃爬蟲的編碼計劃,按照原計劃,預計耗時一個半月可以完成爬蟲的編碼工作。不過在真正動手寫代碼之后,深深的體會到了“理想很豐滿,現實很骨干”這句話的含義。由于當時沒有經驗,編碼過程中犯了很多錯。從一開始的技術選型到實際編碼過程中,自己給自己挖了一個又一個的坑。比如在技術選型階段,選擇了一個難度比較大的并發模型,直接提升了開發難度。另外,在編碼的過程中,也犯了一個比較大的錯誤。即在第一版實現還沒發布前,不斷的加入新功能,導致第一版的爬蟲遲遲出不來,項目最終延期。最后我耗費了3個月的時間,才把第一版的爬蟲發布出來,比預計時間多出一倍。當然,盡管犯了很多錯,但最終還是完成了編寫爬蟲的計劃。總的來說,收獲還是很大的。后面我會把第一版爬蟲所實現的功能點列出來,不過在列之前,先來看看當時爬蟲的一些設計圖。
圖1 爬蟲并發模型:多進程+協程
圖2 爬蟲結構圖
下面來羅列一下第一版爬蟲實現的功能:
以上功能點是我在編碼過程中陸續加入的,這些功能的加入,直接導致了爬蟲第一版實現工期嚴重延誤。同時在編碼的過程中我也踩了很多的坑,當然多數時候都是自己給自己挖的坑,這其中令我印象最深的坑非我選的爬蟲并發模型莫屬了。上面說到了我選擇多進程加協程作為并發模型,是因為擔心 Python GIL 鎖會限制多線程模型的效率。這個模型不用還好,用了之后感覺多太復雜了。首先使用多進程增加了調試的難度,必須要使用遠程調試。其次如果使用協程,基本可以告別調試了,協程調試起來很容易亂掉,所以只能靠打日志。這都不算什么,最坑的是當時我代碼中的協程邏輯不按照預期運行,協程切換很詭異,調試了三天也沒找到原因。最后實在沒辦法,上網求助。最后在知乎上找到了一個 Python 大神,請他在他的電腦上運行我的代碼,看看是否正常。結果他那邊回郵件說正常,并將打印的日志截圖給我。這個就讓我很郁悶了,最后這個問題怎么解決的我也忘了,應該是改代碼規避了。還有其他一些坑,這里就不多說了。
在我的爬蟲寫完并測試好后,就開始正式采數據。我的計劃是采集100萬個網頁,并對采集結果進行一些簡單的數據分析。當我的爬蟲在我那4M的網速上吭哧吭哧的運行了5天之后,數據采集終于完成了。采集的過程中,我也是兢兢業業,每天上完課立馬跑回寢室看看爬蟲的運行狀態,生怕爬蟲掛了。我清楚的記得當數據采集到九十多萬條時,我幾乎沒離開自己的座位,全程盯著爬蟲采完余下的幾萬條數據。待到爬蟲采集數量達到100萬條時,當時興奮的差點沒從座位上跳起來,實在太開心了。現在回想起來,也還是比較欣慰的。當時感覺真的不容易,那段時間除了上課,剩下所有的空閑時間都拿來寫代碼(BUG)了。最關鍵的是,整個編碼過程至始至終只有我一個人參與,沒有隊友。當然,這并不算什么。但是如果一旦碰到比較難的問題,一個人就很郁悶了,連個討論的人都沒有,只能一個人去想辦法解決。好在皇天不負有心人,最終還是完成了。雖然當時花了這么長的時間,僅僅實現了一個較為簡單的爬蟲。但對于當時的我來說,這已經夠了,我從這個過程中還是學到了很多東西。同時,這也是我大學生活一段令我印象深刻的經歷,不管怎么說,都值得了。
上面嘮嘮叨叨的說了很多,不過這仍然不是全部,還有很多細節我已經想不起來了。接下來,給大家看看我當時寫的爬蟲的樣子吧,很簡陋,見笑了。
圖3 爬蟲啟動界面
圖4 爬蟲運行界面
大家可以看到“圖3 爬蟲啟動界面”中的 wormhole 字樣,wormhole 也就是我的爬蟲名稱,這個是我一個字母一個字母敲出來的。圖4是在爬蟲運行了5個小時之后截取的,里面包含了任務總數、完成的任務數、采集失敗的頁面數量和比例、以及當前的采集速度等的。現在看看這兩張圖,內容雖間簡陋,但感覺還是很親切的。另外,在爬蟲完成抓取任務后,我還煞有介事的對采集到的數據進行了一些簡單的分析。比如不同網站所使用的操作系統、腳本語言以及服務器軟件分布比例等。如下:
圖5 數據分析
上面的數據分析是依賴于消息頭進行的,但這樣并不精確。所以參考價值不大,不過也還是有點意思的。
以上就是我與爬蟲技術第一次親密接觸的過程,這次的接觸,令我印象深刻。在編寫爬蟲的過程中,不但達到了最初的目的–熟悉 Python 編程,也順帶學習了很多技術。比如 MongoDB、Bloom Filter、協程等等。盡管寫這個爬蟲耗費了我三個月時間,但從最后的收益來看,這筆投資還是很值得的。如果用大學里經常聽到的一句話總結,那就是:“這波不虧”。
好了,偶遇爬蟲篇,就先說到這了。接下來再來說說大四的利用爬蟲做畢業設計的事情。
?3. 改造開源爬蟲突擊畢業論文
時間過得很快,在我寫完自己的爬蟲不就,大三就結束了。緊接著到了大四,大四上學期快結束時,我們要進行畢業論文選題了。對于畢業論文選題這個事情,我當時的想法很簡單。一定要選一個看起來稍微復雜一點的論文,然后認真完成,并以此論文來為我的大學生活畫上句號。所以思考良久,最終選了基于 Lucene 的全文搜索引擎作為畢設。當然選完之后,我就開開心心的跑出去實習去了,沒再管它了。以至于在畢業答辯的前一個半月,答辯老師讓我們提交答辯申請表的時候,我才想起來還有畢業論文和設計沒準備這回事。于是這就悲劇了,總共一個半月的時間,要留一周的時間進行論文查重和修改,同時答辯前一周還要提交論文最終版,所以真正留給我做畢業設計的時間只有一個月。當時真是急死了,于是最后和公司申請在上班時間寫畢業設計,好在公司答應了我的申請,就這樣我用了一個月的完成了畢業論文和設計。
前面說了,我的畢業論文是關于全文搜索引擎的。看起來并不復雜,調調 Lucene API 就好了。但是,搜索引擎需要數據,而數據又需要拿爬蟲去采集。所以我的畢業設計里不止要實現搜索邏輯,還要附帶實現數據采集邏輯。當然由于時間緊急,加上大三寫的爬蟲跑不起來了,所以就直接找開源的爬蟲框架采數據了。找了一圈,最終選定了黃義華大神寫的?WebMagic?作為我的數據采集工具。盡管當時 Nutch 爬蟲是更好的選擇,但是 Nutch 還是比較復雜的。為了防止出岔子,就選了相對比較簡單的 WebMagic。不過考慮到 WebMagic 工作模式不適合為搜索引擎采集數據,為了能讓 WebMagic 符合我的需求,所以后來我對 WebMagic 源碼進行了一定的改動。這樣它就能同時采集很多個網站的數據,并且在發現新的網站后也會放在任務隊列中,而不是像以前那樣直接過濾掉。在 WebMagic 改造工作接近尾聲時,我用 ExtJS 為 WebMagic 做了簡陋的后臺管理界面,方便我對采集過程進行監視。至于當時我是怎么改動 WebMagic 源碼的,這里就不細說了,我也忘記了。關于改造 WebMagic 的事情就說到這里,下面來看看爬蟲的結構圖以及管理界面:
圖6 畢業設計爬蟲模塊運行界面圖
圖7 畢業設計爬蟲模塊運行界面圖
圖8 新增任務圖
最后再上兩張畢業設計中搜索模塊的界面,如下:
圖9 搜索引擎首頁
圖10 搜索引擎結果頁
以上是我在做畢業設計時,所接觸過的爬蟲。雖然并沒什么亮點,但是在一個月內的時間里,改造別人的開源爬蟲,并采集20W條數據,緊接著編寫搜索邏輯,最后寫畢業論文。整個過程到現在想想,仍然還是很刺激的。好在最后完成了,最終也達到了選題的初衷–通過認真完成畢業論文和設計,為大學生活畫上句號。
?4. 維護公司爬蟲
大學畢業之后,我又是回到了先前實習的公司,并在拿到畢業證后轉正了。由此,我的工作生涯開始了。
我們公司是以給客戶提供搜索服務起家的,既然是搜索服務,自然也離不開爬蟲。公司的爬蟲和業務貼合的比較近,相對于通用爬蟲來說,公司定制的爬蟲還是要復雜的多。擁有很多通用爬蟲沒有的功能,比如對列表頁和詳情頁的識別、對網頁正文的抽取(類似印象筆記的剪藏插件)等。同時,不同于通用爬蟲,我們很多時候在采集客戶的數據(客戶不對我們開放數據)時,經常需要處理各種由 JS 渲染的分頁以及 Ajax 請求等情況。這類數據爬蟲采集不了,這時候就需要人工參與了。怎樣讓人和爬蟲協作,這也不是個簡單問題。我們公司的爬蟲參考了 Nutch 的設計思想,所以也為爬蟲實現了一個插件機制,這樣就解決了人和爬蟲協作的問題。當然具體怎樣實現的,這里就不說了,詳細可以參考 Nutch 的插件機制。
在我來到公司之前,公司的爬蟲就已經存在了。在我一開始工作的時候,感覺公司的爬蟲還是很高大上的,看起來挺復雜的。不過現在看來,也就一般了。設計思想還可以,但易用性不佳。很多可以自動化解決的問題,居然一直都是以人工的方式處理的。舉個例子,有一次,我們公司的運維要檢查爬蟲抓取的數據是否完整。于是他按照慣例到客戶的網站上,從不同的欄目里復制幾條數據的 url。然后再將這幾條 url 一條一條的復制到爬蟲控制臺的搜索框中,看看能不能查找這條 url 的采集記錄。這個過程相對來說還是比較繁瑣的,特別檢查多個網站數據的數據采集情況時,尤為的繁瑣,效率十分低下。所以后來我實在看不下去了,就寫了一個 chrome 插件,并在爬蟲后臺開放一組接口。這樣利用插件批量將頁面中的 url 發送給后臺,后臺檢測完后,再將結果返回給 chrome 插件。插件根據檢測結果,把未爬蟲采集的數據標題標紅,并加上刪除線。這樣哪些數據未被采集,一目了然,再也不用手動檢查了,效率也大大的提高了。
公司現有的爬蟲平臺已經比較老了,有兩三年了,目前看來已經無法滿足業務的需求了。雖然當時在設計上參考了 Nutch 的實現,但也只借鑒了思想,并未借鑒 Nutch 的實現。加之設計之初的技術選型有問題,選用了一些比較底層的技術,導致維護起來很困難。這里并不是說底層技術不好,而是我們公司沒把它用好。所以公司的爬蟲自從寫出來后,幾乎沒更新過,只是偶爾打個 patch,僅此而已。所以大家在做技術選型的時候,好事要慎重考慮,不然以后維護工作是個大麻煩。關于公司的爬蟲就說到這里,保密原因,這里就不貼圖了。
?5. 寫在最后
以上就是我這兩年多學習并使用爬蟲的歷程,雖無什么亮點,但是對我來說卻會比較難忘。從以前不知爬蟲為何物,到今天可以用爬蟲做很多事情。總的來說,還是有比較大的進步吧。當然,我并不非專業的爬蟲工程師,使用爬蟲也只是平時工作的一部分而已。不過即使如此,我仍然覺得數據采集工作并不是個輕松的差事,很繁瑣。當然了,現在除了工作需要,其他時間我幾乎不會再關注爬蟲技術了。我并不打算成為爬蟲工程師,所以這方面的技術夠用就行了。也因為此,寫下這篇文章記錄自己的過往經歷,也算是給自己的爬蟲之路畫上一個句號吧。over!
- 本文鏈接:?https://www.tianxiaobo.com/2018/01/18/我的爬蟲技術經歷/
from:?http://www.tianxiaobo.com/2018/01/18/%E6%88%91%E7%9A%84%E7%88%AC%E8%99%AB%E6%8A%80%E6%9C%AF%E7%BB%8F%E5%8E%86/
總結
- 上一篇: String hashCode 方法为什
- 下一篇: 基于 Zookeeper 的分布式锁实现