爬蟲,幾家歡喜幾人愁。爬者,拿到有利資料,分析行為,產生價值。被爬者,一是損失資料,二是遇到不懷好意的爬蟲往往被全站複製或伺服器受衝擊而無法服務。今天說的是一隻友好的爬蟲是如何構建出來的,請勿用它傷害他人。
爬蟲一生所遇
俗話說,如果我比別人看得遠些,那是因為我站在巨人們的肩上。前人之鑑,後人之師。小爬蟲在胎教的時候就該傳授它的前輩參悟的人生經驗,瞭解網路的可怕之處。看看我提供的胎教課程:
- 被爬網站偶然出現服務無法響應,需重試
- 網站檢查某些header,特別是referer這個引數,請警惕
- 訪問頻率限制,短時間單IP或者單帳號內往往有頻率限制。更高階的還可能用近段時間訪問頻率,時間段請求頻率來識別爬蟲行為。
- 目標爬取網站需要登入
- 網站採用js運算產生最終頁面
小爬蟲身份成謎
爬蟲如此氾濫,網站安能不防備,識別之,封禁之爬蟲就無可奈何了。你問該如何做?我們從tcp/ip的角度來看,網站可以識別到ip地址。那麼如此說來,網站封的很有可能就是ip地址。網路上可是有代理伺服器這種可怕東西存在的,爬蟲依靠代理伺服器偽裝身份,一旦被封禁,換代理又可以愉快的玩耍了。
代理伺服器那裡來?這種東西,用搜尋引擎一搜尋就有了。如果你想省時省力,直接購買。然而在手頭拮据的時候,只能尋找一些免費的代理。一般來說每個網站都會提供一點點免費代理,我們只要勤快定時定後抓取入庫即可,集腋成仇。
千萬不要相信代理伺服器就是可用的,要定時檢查入庫的代理是否有用,除了定時檢查之外,我們還可以藉助squid,我們只要把代理往裡面一丟,爬蟲代理直接設定成squid的ip和埠,這貨就會自動挑選可用代理來使用,省了自己定時檢測。
題外話:免費的往往是最貴的,特別ip,頻寬這種資源。網上提供的代理往往會注入一些廣告js等東西,這個自己想解決方案了。
一個堅持不懈的爬蟲
一隻爬蟲的最高境界就是全自動化,無需人為干預,不過這種事情想想即可,不可能實現的。但是小爬蟲也有自己的修養的,最起碼在各種異常面前不能一次就退縮了吧,出錯重試多次是必須的,最重要的是出現異常程式不能中斷,任務還是得接著完成的。
最簡單的方法是什麼呢?在迴圈裡面搞一個try catch,是不是完美呢?大夥來看看這個例子:
然而這樣子寫是不道德,最重要的還不夠優雅,所以再看看下面這個例子:
應該分別抓取各種錯誤來分別處理,因為各種出錯的應對策略是不一樣的。
小爬蟲也需要團隊作戰
假如說,某一天爬蟲接到任務,一天之內要爬取100萬個網頁。假設一個網頁需要10秒,單程式單執行緒的爬蟲是沒法實現的。這個時候我們可以利用下面幾個方案:
- 多執行緒(然而對於python來說有GIL問題,所以優勢不明顯)
- 多程式,一旦使用多程式就需要解決任務分配問題,和程式管理問題,這個時候我們可以使用訊息中介軟體來分配任務,簡簡單單上一個redis佇列,問題就迎刃而解了。
- 爬蟲叢集,任務分配依舊可以使用訊息中介軟體,而部署我們可以使用偉大的docker,環境都無需配置了。
爬蟲與瀏覽器的愛恨情愁
有很多網站呢,要麼登入的時候需要提交一些js計算後的值。有些資料還要js處理生成,如果我們的爬蟲要模擬js來運算,還得針對每一個網站進行處理,這可一點都不優雅。
那麼咋辦呢?最簡單的方案是,既然我們的瀏覽器能渲染,那麼我們就去呼叫瀏覽器來拿到最終頁面嘛,平時那些稀奇古怪的互動也一併解決了。對於python來說,呼叫瀏覽器一點難度都沒有,因為有神器selenium。
selenium可以很方便的使用python與谷歌呀火狐呀PhantomJS等這些瀏覽器互動,缺點是隻是模擬了GET請求,也許你會說不是可以執行ajax,聽我一句勸,你會被跨域請求坑住的。為了實現其它請求請再上一個庫selenium-requests,然而這庫的使用方法請查考requests,文件這樣子也是無奈。
小爬蟲優雅架構
爬蟲與反爬蟲的較量是長久的,爬取過程千萬要注意抓取頁面異常的情況,觸發反爬蟲預警達到一定次數,帳號或者IP就會被凍結。模擬登陸驗證碼識別可以藉助第三方平臺,起碼比自己寫的驗證碼識別高效得多。