1. 程式人生 > >使用python,scrapy寫(定製)爬蟲的經驗,資料,雜。

使用python,scrapy寫(定製)爬蟲的經驗,資料,雜。

近期找工作略不順。技術無用。晚上寫下了這點東西。

首先說下最近在找工作的x的大概相關技術加點路線。py 3年+,linux日常熟練,限於不擅web、手機app開發,一直無太好的可展示的東西。前段時間從一家小公司離職。年前投下,沒啥的話,年後再看下。先投的py爬蟲的,沒合適的再看運維和py相關其他。

正文開始前略吐槽下,我之前工作的小公司,在我去之前,還是多執行緒urllib爬正則解析,網頁編碼解析從GBK,UTF8依次猜。他有點強讓我走了。

我開始大量使用scrapy時,scrapy已是0.16版。這個版本相對比較成熟,該版本持續了近一年時間,13年夏釋出0.18版。在網上搜scrapy資料,中文的相對較少,為數不多的幾篇也多寫於scrapy較早的版本(提醒看資料注意釋出時間)。從舊資料看,早期的scrapy,還沒有dns解析快取,url去重等功能。到0.16時,scrapy已基本成型,差的幾個功能(如HTTP長連線,仿瀏覽器快取機制(RFCXXXX)的CACHE)陸續在0.18,0.20裡面上實現了。

Scrapinghub(寫scrapy的人搞得公司)上的產品也更豐富了。

scrapy的優點在於成熟完善,定製開發快。

scrapy對比其他我所知的定製爬蟲解決方案。主要對比python內的幾個方案。

JAVA:nutch,hetrix...etc。這幾個更適合做通用爬蟲或少量的定製爬蟲,相對scrapy優點是資料比較多,成熟。不過用java系的寫大量定製爬蟲應該比較痛苦。

Ruby:不瞭解,僅聽說ruby有個爬蟲庫。

Node.js:遇到有個初創團隊用node.js寫的,負責人有scrapy(<0.16),gevent經驗。不瞭解。

python:gevent及其他py的爬蟲框架。稍後會詳細描述這部分。

對於gevent上寫爬蟲的各位,我只能說你們有實力,你們為何要造輪子,你們肯定有自己的理由的,推薦參考下scrapy造輪子。gevent寫爬蟲大概的方案是gevent+requests+一個佇列庫(redis,beanstalk.etc.)。需要注意的點和坑有如下一些。

0,gevent使用協程,monkey_patch後一些除錯方法不可用。

1,requests的編碼檢測是不符標準的,他有兩個編碼,一個是http head裡面的編碼,另一個是依據網頁body的編碼。標準是網頁內容宣告的編碼優先於http頭的編碼,requests沒有做這個考慮,總是使用head裡面的編碼。在head和body編碼宣告不一致時可能出現編碼錯誤。

2,gevent的同步機制略少,某些情況下協程同步效率低。這個是我在寫http代理排程器(類似Crawlera)的東西時遇到的。http代理排程器我下面會提及。

3,其他各種細節。太多。如requests開gzip,requests連線池等等。太多太多。

gevent相對於scrapy的優點有:

1,如果涉及到底層定製 ,gevent比scrapy所用的twisted簡單。我曾想給scrapy嵌一個http代理排程功能,發現略難,需要很瞭解twisted。

2,如果你只需要很少的幾個簡單爬蟲,你可能覺得gevent用著更順手(但scrapy也很容易)。對於純下載網頁,用gevent實現比scrapy快,畢竟scrapy還有其他功能,但這有個前提,你有很高很高的頻寬,要先達到scrapy的下載頁面速率上限。

python還有其他幾個爬蟲框架,我都大致看過原始碼。有個框架有個讓你人工輸驗證碼的demo(名字忘了)。其他沒什麼特別的了。

scrapy經驗,資料

資料:官方文件,http權威指南,一些博文。

看文件時仔細點,很多功能都有。

1,scrapyjs,splash:爬蟲遇到的js問題的解決方法(JS解析會在下面提及)

2,webstruct...etc:機器學習,模糊匹配等用來解析網頁內容的。

3,etc...

scrapy有個SEP類似PEP的,可以一看,也在github的倉庫。

1,定製爬蟲(讓scrapy公司幫你寫爬蟲然後交付你)

2,scrapy cloud(提供跑爬蟲的伺服器(scrapyd))

3,autoscraping(點選需要內容即可實現爬取)

4,crawlera,解決爬網站的ip限制問題(我有一個類似功能的本地版http代理排程器及大量代理)。

一些常見問題,經驗:

0,瞭解scrapy已經做過的功能,優化等。。。防止重複造輪子,如,去重,編碼檢測,dns快取,http長連線,gzip等等。

1,JS相關。

這個是被問的最多的。看具體情況解決。可模擬相關js執行、繞過,或直接調瀏覽器去訪問。自己用一個JS引擎+模擬一個瀏覽器環境難度太大了(參見V8的DEMO)。

調瀏覽器有很多方法。難以細說,關鍵字如下,selenium,phantomjs,casperjs,ghost,webkit,scrapyjs,splash。一些細節如關掉CSS渲染,圖片載入等。只有scrapyjs是完全非同步的,相對是速度最快的,scrapyjs將webkit的事件迴圈和twisted的事件迴圈合在一起了。其他的方案要麼阻塞,要麼用多程序。簡單的js需求(對效率要求不高)隨意選,最優方案是scrapyjs+定製webkit(去掉不需要的功能)。調瀏覽器開頁面是比較耗資源的(主要是cpu)

2,內容解析。

XPATH就可以了,感興趣可以看下pyquery,css選擇器。

如果想獲得網頁對應的txt,可以調瀏覽器,有個類似plain_txt的介面可以獲取網頁儲存成txt。

模糊匹配參考scrapy github裡面幾個庫,機器學習不一定好用(效果問題,人工問題-需要訓練)。還有寫些正則去模糊匹配。

新聞類似的正文提取有readability,boilerplate。

3,分散式。

首先考慮按任務(目標)切分,然後讓不同目標的爬蟲在不同機器上跑

完全的對等分散式(多爬蟲爬一個目標),把任務佇列替換掉爬蟲改改即可。github裡面有幾個現有的實現參考。

分散式需求可能是偽命題。想清楚為何要分散式。硬體夠不夠,像什麼拿一個不支援持久化的url佇列的爬蟲說量大需要分散式的,我只能默唸,你為何這麼吊。

4,部署,排程

部署推薦scrapyd。這也是官方推薦的方法。

大量爬蟲的排程,這個目前(13-10)沒有現成的合適方法,期望是實現爬蟲的某些配置放資料庫,提供web後臺 ,然後按配置週期、定時執行爬蟲,終止,暫停爬蟲等等。可以實現,但要自己寫不少東西。

5,ip限制問題

買的起大量ip的可買(買大量同網段爬可能導致整網段被封)。

找大量免費的開放http代理,篩選可用的,免費開放代理不可靠,寫個排程機制,自動根據成功次數,延遲等選擇合適代理,這個功能難以在scrapy內實現,參考scrapinghub的crawlera,我完成了一個本地版。

6,url去重。

如果有千萬級的URL需要去重,需要仔細看下scrapy的去重機制和bloom filter(布隆過濾器)。bloomfilter有個公式可以算需要多少記憶體。另bloomfilter  + scrapy在github有現有實現可以參考。

7,儲存。

8,硬體扛不住別玩爬蟲。。。曾在I3 4G 1T上跑爬蟲。卡在磁碟io(量大,磁碟io差,記憶體低),出現記憶體佔用飆升。很難除錯(除錯爬蟲看實際跑耗時較長),初步以為是爬蟲有問題記憶體佔用高導致資料庫卡。除錯結果確認為,配置低量太大,導致資料庫慢,資料庫慢之後爬蟲任務佇列佔滿記憶體並開始寫磁碟,又迴圈導致資料庫慢。

9,爬蟲監控

scrapyd自帶簡單的監控,不夠的話用scrapy的webservice自己寫,暫無(13.10)現成的

9,=。=想到再補充。