如何讓爬蟲一天抓取100萬張網頁

      網友投稿 940 2022-05-29

      前一兩年抓過某工商信息網站,幾三周時間大約抓了過千萬多萬張頁面。那時由于公司沒啥經費,報銷又拖得很久,不想花錢在很多機器和帶寬上,所以當時花了較多精力研究如何讓一臺爬蟲機器達到抓取極限。

      本篇偏爬蟲技術細節,先周知。

      爬蟲這兩年貌似成為了一項必備技能,無論是搞技術的,做產品的,數據分析的,金融的,初創公司做冷啟動的,都想去抓點數據回來玩玩。這里面絕大多數一共都只抓幾萬或幾十萬條數據,這個數量級其實大可不必寫爬蟲,使用 chrome 插件 web scraper 或者讓 selenium 驅動 chrome 就好了,會為你節省很多分析網頁結構或研究如何登陸的時間。

      本篇只關注如何讓爬蟲的抓取性能最大化上,沒有使用scrapy等爬蟲框架,就是多線程+Python requests庫搞定。

      對一個網站定向抓取幾十萬張頁面一般只用解決訪問頻率限制問題就好了。對機器內存,硬盤空間,URL去重,網絡性能,抓取間隙時間調優一般都不會在意。如果要設計一個單臺每天抓取上百萬張網頁,共有一億張頁面的網站時,訪問頻率限制問題就不是最棘手的問題了,上述每一項都要很好解決才行。硬盤存儲,內存,網絡性能等問題我們一項項來拆解。

      優化硬盤存儲

      所以千萬級網頁的抓取是需要先設計的,先來做一個計算題。共要抓取一億張頁面,一般一張網頁的大小是400KB左右,一億張網頁就是1億X200KB=36TB?。這么大的存儲需求,一般的電腦和硬盤都是沒法存儲的。所以肯定要對網頁做壓縮后存儲,可以用zlib壓縮,也可以用壓縮率更好的bz2或pylzma 。

      但是這樣還不夠,我們拿天眼查的網頁來舉例。天眼查一張公司詳情頁的大小是700KB 。

      對這張網頁zlib壓縮后是100KB。

      一億個100KB(9TB)還是太大,要對網頁特殊處理一下,可以把網頁的頭和尾都去掉,只要body部分再壓縮。因為一張html頁面里和

      大都是公共的頭尾信息和js/css代碼,對你以后做正文內容抽取不會影響(也可以以后做內容抽取時把頭尾信息補回去就好)。

      來看一下去掉頭尾后的html頁面大小是300KB,壓縮后是47KB。

      一億張就是4T,差不多算是能接受了。京東上一個4T硬盤600多元。

      優化內存,URL去重

      再來說內存占用問題,做爬蟲程序為了防止重復抓取URL,一般要把URL都加載進內存里,放在set()里面。拿天眼查的URL舉例:

      https://www.tianyancha.com/company/23402373

      這個完整URL有44個字節,一億個URL就是4G,一億個URL就要占用4G內存,這還沒有算存這一億個URL需要的數據結構內存,還有待抓取URL,已抓取URL還保存在內存中的html等等消耗的內存。

      所以這樣直接用set()保存URL是不建議的,除非你的內存有十幾個G。

      一個取巧的辦法是截斷URL。只把URL:

      https://www.tianyancha.com/company/23402373

      的后綴:23402373放進set()里,23402373只占8個字節,一億個URL占700多M內存。

      但是如果你是用的野云主機,用來不斷撥號用的非正規云主機,這700多M內存也是吃不消的,機器會非??ā?/p>

      就還需要想辦法壓縮URL的內存占用,可以使用BloomFilter算法,是一個很經典的算法,非常適用海量數據的排重過濾,占用極少的內存,查詢效率也非常的高。它的原理是把一個字符串映射到一個bit上,剛才23402373占8個字節,現在只占用1個bit(1字節=8bit),內存節省了近64倍,以前700M內存,現在只需要10多M了。

      BloomFilter調用也非常簡單,當然需要先install 安裝bloom_filter:

      from?bloom_filter?import?BloomFilter#?生成一個裝1億大小的bloombloom?=?BloomFilter(max_elements=100000000,?error_rate=0.1)#?向bloom添加URLbloom.add('https://www.tianyancha.com/company/23402373')#判斷URL是否在bloombloom.__contains__('https://www.tianyancha.com/company/23402373')

      不過奇怪,bloom里沒有公有方法來判斷URL是否重復,我用的__contains__()方法,也可能是我沒用對,不過判重效果是一樣的。

      反抓取訪問頻率限制

      單臺機器,單個IP大家都明白,短時間內訪問一個網站幾十次后肯定會被屏蔽的。每個網站對IP的解封策略也不一樣,有的1小時候后又能重新訪問,有的要一天,有的要幾個月去了。突破抓取頻率限制有兩種方式,一種是研究網站的反爬策略。有的網站不對列表頁做頻率控制,只對詳情頁控制。有的針對特定UA,referer,或者微信的H5頁面的頻率控制要弱很多。我在這兩篇文章有講到《爬蟲小偏方:繞開登陸和訪問頻率控制》《?爬蟲小偏方二:修改referer后可以不用登錄了》。

      另一種方式就是多IP抓取,多IP抓取又分IP代理池和adsl撥號兩種,我這里說adsl撥號的方式,IP代理池相對于adsl來說,我覺得收費太貴了。要穩定大規模抓取肯定是要用付費的,一個月也就100多塊錢。

      adsl的特點是可以短時間內重新撥號切換IP,IP被禁止了重新撥號一下就可以了。這樣你就可以開足馬力瘋狂抓取了,但是一天只有24小時合86400秒,要如何一天抓過百萬網頁,讓網絡性能最大化也是需要下一些功夫的,后面我再詳說。

      至于有哪些可以adsl撥號的野云主機,你在百度搜"vps adsl",能選擇的廠商很多的。大多宣稱有百萬級IP資源可撥號,我曾測試過一段時間,把每次撥號的IP記錄下來,有真實二三十萬IP的就算不錯了。

      選adsl的一個注意事項是,有的廠商撥號IP只能播出C段和D段IP,110(A段).132(B段).3(C段).2(D段),A和B段都不會變,靠C,D段IP高頻次抓取對方網站,有可能對方網站把整個C/D段IP都封掉。

      C/D段加一起255X255就是6萬多個IP全都報廢,所以要選撥號IP范圍較寬的廠商。 你要問我哪家好,我也不知道,這些都是野云主機,質量和穩定性本就沒那么好。只有多試一試,試的成本也不大,買一臺玩玩一個月也就一百多元,還可以按天買。

      上面我為什么說不用付費的IP代理池?

      因為比adsl撥號貴很多,因為全速抓取時,一個反爬做得可以的網站10秒內就會封掉這個IP,所以10秒就要換一個IP,理想狀況下一天86400秒,要換8640個IP。

      如果用付費IP代理池的話,一個代理IP收費4分錢,8640個IP一天就要345元。 adsl撥號的主機一個月才100多元。

      adsl撥號Python代碼

      怎么撥號廠商都會提供的,建議是用廠商提供的方式,這里只是示例:

      windows下用os調用rasdial撥號:

      import?os#?撥號斷開os.popen('rasdial?網絡鏈接名稱?/disconnect')#?撥號os.popen('rasdial?網絡鏈接名稱?adsl賬號?adsl密碼')

      linux下撥號:

      import?os#?撥號斷開code?=?os.system('ifdown?網絡鏈接名稱')#?撥號code?=?os.system('ifup?網絡鏈接名稱')

      網絡性能,抓取技術細節調優

      上面步驟做完了,每天能達到抓取五萬網頁的樣子,要達到百萬級規模,還需把網絡性能和抓取技術細節調優。

      1.調試開多少個線程,多長時間撥號切換IP一次最優。

      每個網站對短時間內訪問次數的屏蔽策略不一樣,這需要實際測試,找出抓取效率最大化的時間點。先開一個線程,一直抓取到IP被屏蔽,記錄下抓取耗時,總抓取次數,和成功抓取次數。 再開2個線程,重復上面步驟,記錄抓取耗時,總的和成功的抓取次數。再開4個線程,重復上面步驟。整理成一個表格如下,下圖是我抓天眼查時,統計抓取極限和細節調優的表格:

      從上圖比較可以看出,當有6個線程時,是比較好的情況。耗時6秒,成功抓取80-110次。雖然8個線程只耗時4秒,但是成功抓取次數已經在下降了。所以線程數可以設定為開6個。

      開多少個線程調試出來了,那多久撥號一次呢?

      從上面的圖片看到,貌似每隔6秒撥號是一個不錯的選擇??梢赃@樣做,但是我選了另一個度量單位,就是每總抓取120次就重新撥號。為什么這樣選呢?從上圖也能看到,基本抓到120次左右就會被屏蔽,每隔6秒撥號其實誤差比較大,因為網絡延遲等各種問題,導致6秒內可能抓100次,也可能抓120次。

      2.requests請求優化

      要優化requests.get(timeout=1.5)的超時時間,不設置超時的話,有可能get()請求會一直掛起等待。而且野云主機本身性能就不穩定,長時間不回請求很正常。如果要追求抓取效率,超時時間設置短一點,設置10秒超時完全沒有意義。對于超時請求失敗的,大不了以后再二次請求,也比設置10秒的抓取效率高很多。

      3.優化adsl撥號等待時間

      上面步驟已算把單臺機器的抓取技術問題優化到一個高度了,還剩一個優化野云主機的問題。就是每次斷開撥號后,要等待幾秒鐘再撥號,太短時間內再撥號有可能又撥到上一個IP,還有可能撥號失敗,所以要等待6秒鐘(測試值)。所以要把撥號代碼改一下:

      import?os#?斷開撥號os.popen('rasdial?網絡名稱?/disconnect')time.sleep(6)#?撥號os.popen('rasdial?網絡名稱?adsl賬號名?adsl密碼')

      而且 os.popen('rasdial 網絡名稱 adsl賬號名 adsl密碼') 撥號完成后,你還不能馬上使用,那時外網還是不可用的,你需要檢測一下外網是否聯通。

      我使用 ping 功能來檢測外網連通性:

      import?os?code?=?os.system('ping?www.baidu.com')

      code為0時表示聯通,不為0時還要重新撥號。而ping也很耗時間的,一個ping命令會ping 4次,就要耗時4秒。

      上面撥號等待6秒加上 ping 的4秒,消耗了10秒鐘。上面猿人學Python說了,抓120次才用6秒,每撥號一次要消耗10秒,而且是每抓120次就要重撥號,想下這個時間太可惜了,每天8萬多秒有一半時間都消耗在撥號上面了,但是也沒辦法。

      當然好點的野云主機,除了上面說的IP范圍的差異,就是撥號質量差異。好的撥號等待時間更短一點,撥號出錯的概率要小一點。

      通過上面我們可以輕松計算出一組抓取的耗時是6秒,撥號耗時10秒,總耗時16秒。一天86400秒,就是5400組抓取,上面說了一組抓取是120次。一天就可以抓取5400X120=64萬張網頁。

      按照上述的設計就可以做到一天抓60多萬張頁面,如果你把adsl撥號耗時再優化一點,每次再節約2-3秒,就趨近于百萬抓取量級了。

      另外野云主機一個月才100多,很便宜,所以你可以再開一臺adsl撥號主機,用兩臺一起抓取,一天就能抓一百多萬張網頁。幾天時間就能鏡像一個過千萬網頁的網站。

      知識Tips:

      1.為什么不用異步抓取?

      沒必要,這里的整個抓取關鍵是網絡性能,而不是程序性能。用異步把程序性能提高了,單位時間的抓取次數是提高了,但是這樣反而會擊中對方網站的訪問頻率控制策略。

      如何讓爬蟲一天抓取100萬張網頁

      2.要計算對方的帶寬壓力,不要抓取太過分了

      抓取歸抓取,但不要影響對方網站,把對方網站帶寬都打滿了。

      一個中小型網站的帶寬在5M以內,大一點的網站帶寬可能10-30M,超大型的另算。

      一張網頁300KB,對方一般會壓縮后傳輸給瀏覽器,就按壓縮后30KB算,你的爬蟲一秒請求20次,帶寬就是600KB??赡芤粋€網站每天都有幾十個爬蟲都在爬,我們按有10個爬蟲在同時抓取,就是這些爬蟲一秒內就要消耗600KBX10=6M帶寬。

      再加上還有正規爬蟲,人家網站上的正常用戶訪問這些,算下來可能一共要消耗10M帶寬。一般的大中型網站都是吃不消的。

      python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:程序員硬核測評:全方位測評 GaussDB(for Redis) 和開源 Redis
      下一篇:對象存儲服務訪問控制原理介紹(四):使用場景
      相關文章
      亚洲第一视频网站| 亚洲精品国产日韩| 亚洲av成人无码网站…| 校园亚洲春色另类小说合集| 亚洲日本成本人观看| 国产偷国产偷亚洲高清日韩| 亚洲精品亚洲人成在线麻豆| 妇女自拍偷自拍亚洲精品| 久久精品亚洲综合一品| 亚洲av成人片在线观看| 亚洲一级二级三级不卡| 亚洲人xxx日本人18| 中文字幕亚洲第一| 久久久久亚洲AV片无码下载蜜桃| 亚洲自国产拍揄拍| 中文字幕不卡亚洲 | 国产AV无码专区亚洲AWWW| 亚洲人成综合网站7777香蕉| 亚洲av无码一区二区三区乱子伦| 久久久久亚洲AV无码观看| 亚洲国产成人VA在线观看 | 亚洲国产精品成人| 欧美激情综合亚洲一二区| 亚洲av中文无码乱人伦在线播放 | 亚洲伊人色一综合网| 亚洲精品无码国产| 亚洲AV色无码乱码在线观看| 亚洲国产成+人+综合| 亚洲VA中文字幕无码一二三区| 噜噜噜亚洲色成人网站| 在线亚洲午夜片AV大片| 亚洲av成人无码久久精品| 亚洲午夜成人精品电影在线观看| 亚洲最大的视频网站| 亚洲AV无码一区二区乱子伦| 狠狠色婷婷狠狠狠亚洲综合| 亚洲人成色77777在线观看| 亚洲高清无在码在线无弹窗| 久久精品亚洲福利| 亚洲日韩精品国产3区| 亚洲成人黄色网址|