那些年我們一起寫過的Python爬蟲

在一家能從業務裏源源不斷產生數據的公司工作是一件很幸福的事情,但很多人如我就沒有這樣幸運。沒有數據又想蹭住人工智能的風口,一種方法是潛心學術研究算法,但用來做實驗的數據往往都是學術界或者一些好心的工業界提供的低配版數據,練就的屠龍刀倚天劍離實戰還有很多距離;另一種方法就是費盡心機尋找真實數據。在聊(已經學不動的)各種神乎其技的算法之餘,我也想簡單總結下那些年我們寫爬蟲的經驗。

甄選網站

寫爬蟲之前先要從需求出發尋找合適的目標網站和數據源。

首先,能有API調用或者能從別的渠道買到的數據就儘量別再自己寫爬蟲了。除非目標網站的數據非常容易爬,否則寫爬蟲是一個非常繁瑣且需要長期鬥爭的體力活。從各個IT大廠的雲服務,到一些爬蟲起家的數據公司,甚至在某寶上面,都有大量的API或者數據的服務。首選API的服務因爲一般數據提供商會按照API調用次數收費,配合API的query條件可以比較好滿足自己的特定需求,數據提供商一般也會保持數據更新;如果是直接買數據一開始報價中就要談好更新數據的後續報價。

幾個數據源的例子,比如百度數據開放平臺:

香港政府的資料一線通(更新很快,最新的冠狀病毒數據也已經傳在上面並且保持更新):

如果真的要自己寫爬蟲,那就要開始調研目標數據所在的網站。一般都會有多個網站提供目標數據,我們要挑看上去數據簡單排列整齊的(一個表格很多下一頁那種),排版看上去土土的(網頁代碼簡單好寫parser),沒有太多控件,最好也不用賬戶登錄更不要沒事跳出一個驗證碼的那就是墜好的。越冷門的網站一般也越好,因爲可能訪問量不高,網站管理者也不會設置太多的爬蟲限制。

業務方常常會提出比如去幾千個不同網站上去分別爬取信息的需求。這是不現實的,因爲我們並不是谷歌或者百度這樣的搜索引擎,不同網站結構不一樣,意味着我們可能要分別寫幾千個爬蟲才能爬取所有的信息,更不要提之後的維護工作。最佳的情況是目標數據存在同一個網站內,網頁結構單一可以直接一次性爬取,後續維護工作也比較簡單。有時候我們也會爬兩到三個不同的網站然後做數據的cross validation,因爲有的網站數據不見得是完整正確的,甚至一些網站檢測到爬蟲還會主動給你feed假數據…

爬蟲框架

市面上有多種不同的爬蟲框架可以選擇,不同的框架也可能基於java或者python等的不同語言。如scrapy這樣的爬蟲包已經將很多爬蟲功能如多線程並行爬取等打包實現。

當年自己寫爬蟲主要是python棧,簡單的流程就是使用selenium做框架,phantomJS做模擬瀏覽器拿到源代碼,然後用xpath或者beautifulSoup做網頁解析得到目標數據。解析前一般會用chrome的debug模式先直接在網頁中測試xpath的解析邏輯是否靠譜:

相應的爬蟲代碼教程很多,這裏不再囉嗦。

搏鬥經驗

寫完爬蟲代碼,把代碼跑起來,這纔是一條爬蟲和目標網站搏鬥的剛剛開始…下面是冰山一角的幾條經驗:

  1. 斷點續爬。這個很重要,因爲你的網絡很可能不穩定,中間爬蟲很可能會斷掉。如果每次斷掉都重頭開始爬數據可能永遠也爬不完,所以一定也寫好error handling也就是try exception的部分,connection error之類發生以後要及時等待重試而不是退出程序。
  2. 瀏覽器加header。這個也很重要,因爲很多時候如果網站服務器發現你明顯是一個headless的爬蟲瀏覽器會即刻拒絕掉你的網絡請求。一個典型的header如下:{‘Accept’: ‘/’, ‘Accept-Language’: ‘en-US,en;q=0.8’, ‘Cache-Control’: ‘max-age=0’, ‘User-Agent’: ‘Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36’, ‘Connection’: ‘keep-alive’, ‘Referer’: ‘http://www.baidu.com/’ }
  3. 模擬登錄、隨機等待時間等等,這些都是爲了模擬真實用戶的行爲,防止激活網站的反爬蟲機制封殺掉你。
  4. 如果不幸你的ip被網站封殺了,就需要使用ip代理繼續爬取數據。實際上ip代理是爬蟲中非常重要的一環。有了大量代理ip就可以放心做多線程爬取,一個ip封掉可以自動及時替換爲另一個ip。網上有一些免費的ip代理服務,但是速度和穩定性都不夠;一般推薦付費的ip代理服務如kuaidaili,會提供API直接調取和動態更新代理池,穩定度也會好很多。
  5. 爬蟲維護。網站改版、網址改動、新數據上線等都可能造成原先的爬蟲不再適用,加上目標網站的IT也會不斷更新反爬蟲策略,所以爬蟲維護是一個持久戰。

另一個障礙是很多網站爲了防止爬蟲還會設置有驗證碼。不過道高一尺魔高一丈,我曾經也和各種驗證碼搏鬥過一些時間,而且這個經驗很有意思,我下面單獨聊聊。

幹掉驗證碼

比較古舊的網站驗證碼往往是如下的樣子:

這種驗證碼的破解方式其實就是訓練一個OCR的模型去模擬人識別這些扭曲變形或者不同背景的文字。然後訓練一個針對某一種驗證碼的OCR系統是需要大量訓練數據訓練一個圖像識別模型的。莫非我們還要去大量爬取驗證碼圖片先?實際中大部分情況的做法是,通過觀察驗證碼的樣式,寫一些簡單的規則自己生成類似的驗證碼。比如調整字體,隨機做圖片扭曲,加一些橫豎的裂紋線,或者加上不同背景花紋和顏色等等。規則寫好,就相當於有一套系統可以隨機生成無限多的訓練數據,這樣就可以當作用如卷積網絡這樣的模型,最後面一層是26個英文字母的分類,訓練出一個驗證碼識別的模型。

我們當年的實際情況是遇到了中文驗證碼,而且是中文或者成語,有時候還是數學公式:

這就大大加大了模型驗證的難度,因爲漢字個數要遠遠大於英文字母的個數。不過對於成語來講,我們又單獨爬取了一個成語庫。這樣對於識別出來的四字中文如果有一兩個識別錯了,我們會計算相似度從成語庫中找到最相近的正確成語,這樣就大大提高了識別的準確度。

當我們的深度學習驗證碼識別系統完美工作,爬取了數天數據之後,我們發現網站忽然改版了。新的驗證碼變成了這樣:

要找到拼圖,然後拖動滑塊到拼圖的附近纔可以成功。

於是我們再次用圖像處理的方法找到拼圖,卻發現如果只是直接模擬把滑塊拖過去依然會驗證失敗。我們找到了這家驗證碼服務的提供商,然後發現他們的文檔裏說他們也使用了人工智能技術來通過拖動滑塊的鼠標軌跡和速度以及拼圖契合度來判斷是真人還是機器人…如果勻速直線拖過去然後完美契合拼圖也會悲劇。

於是我又用了將近一個月的時間研究如何模擬出完美的鼠標軌跡來騙過驗證碼。當年的成果現在還在 github裏面躺着 ,有興趣的讀者可以去挖一下墳。那時候已經崩潰到考慮用強化學習Reinforcement Learning來做破解了…

現今的驗證碼已經基本到了神乎其技的階段了。以Google爲例,居然在用驗證碼幫助收集圖像識別的標註數據,也是真的醉了…

總結很多人學Python過程中會遇到各種煩惱問題,沒有人解答容易放棄。爲此我建了個python學習資源羣裏面有最新學習資料

推薦我們的Python學習扣qun:784758214 ,看看前輩們是如何學習的!從基礎的python腳本到web開發、爬蟲、django、數據挖掘等【PDF,實戰源碼】,零基礎到項目實戰的資料都有整理。送給每一位python的小夥伴!每天都有大牛定時講解Python技術,分享一些學習的方法和需要注意的小細節,點擊加入我們的 python學習者聚集地

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章