scrapy: 使用HTTP代理繞過網站反爬蟲機制

下面的鏈接是我在python3.4 和Scarpy1.2上的實現的代理中間件

http://blog.csdn.net/letunihao/article/details/52350437

Table of Contents

1 簡介

最近接了個私活, 一同學在爬雪球網的數據時, 經常被雪球網以IP短時間內過多次訪問爲由要求輸入驗證碼, 導致爬蟲無法長時間運行. 一開始他的想法是用python的一些庫自動識別驗證碼, 或者網上找一些人工輸入驗證碼的服務來解決這個問題. 但是我看了一下雪球網的驗證碼還是挺複雜的, 肉眼看都不太好認, 自動識別應該是不行了. 至於人工打碼服務, 看了一下他們的網站覺得整個一副”我有病毒, 我很山寨”的樣子, 就完全不想用了. 於是我決定用HTTP代理來避免IP被禁就無法繼續爬的問題.

經過一番調研, 國內提供穩定可靠的HTTP代理的服務基本沒有. 國外倒是找到兩個, 其中一個提供試用, 但是不知道爲什麼連不上他們的代理. 另一個最便宜也要$25/月, 錢倒是小事(反正不是我出), 但是不試用過不知道效果怎麼樣, 最終都放棄了. 另外還有個tor, 提供不定時的切換IP, 理論上來說是最適用我的需求的, 奈何一來連tor需要翻牆, 二來網速實在是慢. 最終決定試用網上免費提供的大陸高匿代理.

2 設計

scrapy提供下載中間件機制, 可以在請求隊列與下載請求之間做一些動作. scrapy本身也提供了一個ProxyMiddleware, 但是它只能使用固定的IP地址, 由於免費的代理相當不穩定, 很多代理其實根本不能用. 因此需要對ProxyMiddleware改造使得這個middleware能夠發現代理不可用, 並且在發現不可用的時候切換到另一個代理.

scrapy提供的ProxyMiddleware相當簡單, 對其改造基本上等同於重新寫一個了…首先就是如何發現一個代理不可用. 最常見的不可用代理的症狀就是超時或者拒絕服務, 完全連不上, 爲了處理這個問題, 新的ProxyMiddleware就要在process_exception裏捕捉超時和ConnectionRefused異常. 還有些代理的問題是直接返回403或者407. 於是還要在process_response中檢查response的status.

發現異常之後要換新的代理, 所以在新的ProxyMiddleware中需要一個list來保存所有代理, 每個代理還要有些屬性, 例如valid, 這樣當發現一個代理根本連不上時將valid屬性設爲False, 下次需要換代理時就忽略這些valid爲False的代理, 避免再經歷一遍超時.

另外就是發現IP被ban了之後更換代理, 一開始我是直接在middleware裏處理這種情況, 但是IP被ban的檢查各個網站都不一樣, 寫死在middleware裏不太好. 於是我在spider裏檢查是否被ban, 如果被ban了則重新yield一個請求, 並設置meta["change_proxy"]=True, 然後在middleware裏的process_request處檢查這個屬性, 如果爲True則更換代理.

還有個問題就是代理數量不足的問題. 由於免費代理一般都是臨時性的, 隨着運行時間的增長, 有些代理會失效, 這樣到最後就沒有可用的代理了. 於是我在新的ProxyMiddleware裏, 每次換新代理時檢查代理列表中有效代理的數量, 如果小於一個閾值, 則從網上抓新的免費代理擴充代理列表.

3 實現

抓免費代理的腳本

這個腳本用於爲了獲取免費代理, 由於是爲雪球網設計的, 主要抓的是大陸的高匿代理. 代碼見https://github.com/kohn/HttpProxyMiddleware/blob/master/fetch_free_proxyes.py

抓代理的時候會簡單篩選一下響應時間, 這個數據是提供免費代理的網站提供的.

4 坑

光寫個middleware其實一天就寫好了, 接着又花了一天調參數. 然後在用到實際項目中去的時候就是與坑作鬥爭的血淚史.

有些代理根本不按常理出牌, 簡單歸納一下:

  1. 將URL重定向到一個格式不合法的URL, 例如http://xueqiu.com/ 它給重定向到了http://xueqiu.com/http://xueqiu.com/. 通過設置request的dont_redirect屬性以及檢查302來解決
  2. 返回404, 500等各種各樣的status. 解決方法是一個個加到檢查列表裏去(直接檢查不等於200就換代理理論上應該可行)
  3. 最坑的就是雖然不好用, 但是返回的status是200! 只不過內容是一行錯誤信息. 這種錯誤在middleware里根本沒法檢查, 因爲有些response的內容是一行錯誤信息說”… was not found on this server”(沒找到你倒是返回404 啊), 而有些返回的內容是一個廣告網站…這種代理只有在spider的parse裏檢查了, 如果找不到需要的內容, 就新建一個request, 設置meta["change_proxy"]=True來要求middleware換代理.
  4. 各種坑層出不窮, 防不勝防, 最終決定在獲取免費代理時, 首先使用免費代理爬取一個測試用的網頁, 如果能夠爬下來並且比較過內容之後發現確實是目標網頁, 則認爲這個代理可用.

除了可用性之外, 在實際應用過程中還有一些效率上的問題需要優化.

  1. 使用代理總是比不使用代理要慢, 因此實現時用到了一個定時器, 當發現已經兩小時沒有用原生的連接(就是不用代理)去爬網頁時, 自動切換到不用代理的情況.
  2. 運行過程中可能會出現”抖動”的問題, 當已有的n個代理都能正常使用, 但是被ban了, 就會不斷的在這n個代理之間切換而實際上什麼都沒抓下來, 解決方法時定時(如半小時)抓取新的代理.

5 想法

寫爬蟲繞過網站的反爬蟲機制應該是一個比較通用的需求, 但是國內竟然沒有針對這一需求提供商業解決方案的公司. 如果能實現一箇中間代理, 使得用戶只要簡單的將他的爬蟲的代理設置爲我的中間代理的URL, 然後由這個中間代理再去使用另一個代理根據用戶需求抓數據, 並且能根據需要或者定時更換代理, 這樣用戶只要簡單的設置一個代理, 就能實現IP的不斷切換了, 這種服務應該能有盈利空間吧.

http_proxy_middleware_idea.png


https://github.com/kohn/HttpProxyMiddleware

https://github.com/cocoakekeyu/autoproxy

http://blog.csdn.net/xiao4816/article/details/50650075

發佈了46 篇原創文章 · 獲贊 10 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章