如何優化 Python 爬蟲的速度?

目前在寫一個 Python 爬蟲,單線程 urllib 感覺過於慢了,達不到數據量的要求(十萬級頁面)。求問有哪些可以提高爬取效率的方法?


考慮用多進程+分布在不同機房的集群。

理由如下:
如果單進程,則瓶頸多出在CPU上。

多進程的話可以高效利用CPU。但是其實多數情況是在網路,所以說更好的解決辦法是用多個機房的多台機器同時跑多進程的爬蟲,這樣減少網路阻塞。

實現的話,用scrapy+rq-queue然後用redis來作隊列就好。

用這個方法爬過douban的幾千萬個頁面

請參考我在另一個問題里的回答:
Python 爬蟲如何入門學習?


謝邀。
爬蟲下載慢主要原因是阻塞等待發往網站的請求和網站返回
解決的方法是採用非阻塞的epoll模型。
將創建的socket連接句柄和回調函數註冊給操作系統,這樣在單進程和單線程的情況下可以並發大量對頁面的請求。
如果覺得自己寫比較麻煩,我用過現成的類庫:tornado的非同步客戶端
http://www.tornadoweb.org/documentation/httpclient.html
如果你打不開增加host或翻牆
host地址:
74.125.129.121 http://www.tornadoweb.org


1.開啟gzip
2.多線程
3.對於定向採集可以用正則取代xpath
4.用pycurl代替urlib
5.換個帶寬高的環境


你可以試試直接使用開源的爬蟲庫scrapy,原生支持多線程,還可以設定抓取速率,並發線程數等等參數;除此之外,scrapy對爬蟲提取HTML內容也有良好的支持。

網址:http://scrapy.org/
中文入門教程也已經問世,可以Google一下。


前一陣金融系的同學委託我寫個Python爬蟲從某小額信貸網站爬訂單細節(公開的),共20萬條,用了多線程還是嫌慢。比較奇怪的是這麼頻繁的訪問它不封我IP…最後一個搞安全的同學幫我直接拖庫了。


用 Asynccore 之類手寫。看看 Twisted 有沒有非阻塞、非同步的 HTTP client 框架。
用過 multiprocessing 包 + utllib 做 http client 速度相當不理想,線程應該會好但我的直覺是提升有限。
----
推薦 gevent + grequests


主要是判斷准目前的瓶頸在哪裡,網路io、磁碟io,還是cpu、內存等。然後在給出解決方案,io問題可以考慮添加硬體或者分散式;如果只cpu佔用不飽和,可以考慮多線程、多進程、非同步等,也的看具體情況。按照你的描述,猜測問題應該在cpu佔用不飽和。


對Python來說,最好分割任務 + 多進程


from multiprocessing.dummy import Pool


gevent,eventlet,pycurl


1.dns cache
2. 多線程
3. 非同步io


把爬蟲伺服器放在和你要爬的網站同一個機房...


如果編程能力是瓶頸的話
增加多線程的特性是最具性價比的了
花不了多少開發的時間的

之後的話問題就多了
代碼也不是幾行能搞定的了

  • cpu瓶頸的話可以通過分散式的方式來解決
    更多的結點去處理分發的任務就好了
  • 本地帶寬的瓶頸通過雲伺服器解決(一般都有100MB的方案提供)
    定時定量的去購買使用可以節約成本(畢竟不是搜索引擎不會一直開著的)
  • 目標伺服器的帶寬限制(基於IP的)通過跨區的伺服器解決
    雲伺服器提供商有多個機房的
    分散節點所在的機房可以緩解問題
    有提供動態ip的就更好了
  • 目標伺服器的訪問限制
    搜一下&<反爬蟲&>策略就差不多了解了
    根據自己的編程能力來應對
    給兩個庫投石問路 SeleniumPhantomJS
    對於驗證碼相關的可以考慮購買服務(有外包的, 最高級別是人肉的一定可以搞定, 量要考慮一下價格不菲)真的不建議自己搞
    目標網站系統比較知名的話(discuz)可以網上搜搜
    足夠簡單的話可以用opencv(有python綁定的版本而且跨平台)
    thredshold(二值化)處理顏色, eroded/dilate(腐蝕膨脹)處理噪點, findContours(查找輪廓)處理字元分割,窮舉旋轉和簡單扭曲再匹配字型檔差不多就可以處理2010以前的簡單二維碼了(當然cpu開銷還是很大的)
  • 目標伺服器的帶寬上限限制
    這麼做的話你的爬蟲就成了攻擊了不討論
    ----以下內容常規的爬蟲可能不會涉及--------------------------------------------------------------------------------
  • 文件系統的瓶頸
    如果需要保存爬下來的文件, 那文件系統在單個文件夾下文件過多時的性能下降就要考慮了
    考慮編碼瓶頸最起碼的目錄要獨立文件管理了(10w+的時候)因為列目錄就可能卡機了,如果是桌面端的話就得重啟了
    能編碼的話可以考慮簡單的進行額外的管理(資料庫管理也是不錯的選擇)
  • 可視化/工具化的瓶頸
    需要做成工具的要考慮這個問題(比如Golang的Pholcus), 桌面開發有瓶頸的話可以做Web版本的界面
    需要跨平台的界面則需要第三方的框架支持比較好
    但更重要的是, 爬蟲的進度需要可見, 所以之前的設計如果沒有考慮這點的話, 改動會比較大
    針對大文件可能需要詳細的進度(這樣阻塞模式的下載就不太靠譜了)需要多線程斷點續傳(這個改動更大)任務本身也可能需要考慮持久化了
  • 推廣/維護的瓶頸
    推廣的話爬蟲自身支持的規則就是瓶頸了, 比如各大漫畫爬蟲軟體. 支持的網站多寡就成了核心競爭力, 是否支持規則擴展?是否有人維護規則有效性?這些都是問題, 需要額外的人力投入的

很多人提到了grequests(gevent + requests) 但是這東西在2000多個請求之後就崩潰了。(OSerror: Too many open files).推薦用frequests,grequests同樣的API,但是更加穩定。

i-trofimtschuk/frequests 路 GitHub


用node寫過爬蟲,雖然語言不同,但技術是相通的,希望有幫助

node寫的爬蟲,單進程,總訪問量在24w左右,完全抓取一次大概在80分鐘左右,瓶頸主要在帶寬和網站限制上。

優化技巧總結起來無外乎多線程,提高吞吐率上

1、數據抓取和數據處理分離,使用多線程或多進程將兩個任務分開處理,避免互相影響

2、使用多線程在不被封鎖的情況下盡量多的抓取網頁,視數據量決定抓取的內容存放在內存中或硬碟中

3、使用流水線思維加多線程實現頁面處理流水線化,將爬蟲邏輯分為數據抓取、數據預處理,數據處理,數據保存幾個步驟,步驟之間相互並行

4、有一個經常被忽視的地方需要注意,如果數據抓取速度過快,那麼爬蟲的瓶頸往往在cpu上,而cpu主要消耗在對html的解析上,必要時需要自己實現一個基於字元串查找的html解析器,可以消除這一瓶頸。


gevent + requests, 支持自動復用連接 支持gzip


先用簡單的多線程模型改造一下,基本能夠可用的數量級,我就是這樣弄的。小文件100threads,100qps是沒問題的,基本達到網路IO的極限。
在網上的話,建議自己根據業務性質調整


首先,不要把寶貴的CPU時間浪費在阻塞上
其次IO瓶頸沒錢沒辦法,有錢就有辦法


對於cpu密集型建議別用python多線程 不要忘了cpython的global interperater lock 不過你這個情況io應該是瓶頸,建議使用epoll等非同步io


總覺得寫爬蟲,還是不要給被爬網站造成太大傷害比較好,這樣對大家都好。 (~ ̄▽ ̄)~


推薦閱讀:

為什麼網路爬蟲好難,涉及到的知識我不會?
做python爬蟲需要會web後端嗎,不會的話能做嗎?
python3爬蟲中文亂碼問題求解?(beautifulsoup4)
求大神們推薦python入門書籍(爬蟲方面)?
python動態的網頁數據json里沒有中文字元怎麼辦?

TAG:Python | 爬蟲計算機網路 |