溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python爬蟲一天抓取百萬張網(wǎng)頁的方法是什么

發(fā)布時(shí)間:2020-08-20 09:26:27 來源:億速云 閱讀:350 作者:小新 欄目:編程語言

小編給大家分享一下Python爬蟲一天抓取百萬張網(wǎng)頁的方法是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、優(yōu)化硬盤存儲

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

Python爬蟲一天抓取百萬張網(wǎng)頁的方法是什么

二、優(yōu)化內(nèi)存,URL去重

再來說內(nèi)存占用問題,做爬蟲程序?yàn)榱朔乐怪貜?fù)抓取URL,一般要把URL都加載進(jìn)內(nèi)存里,放在set()里面。拿天眼查的URL舉例:

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

這個(gè)完整URL有44個(gè)字節(jié),一億個(gè)URL就是4G,一億個(gè)URL就要占用4G內(nèi)存,這還沒有算存這一億個(gè)URL需要的數(shù)據(jù)結(jié)構(gòu)內(nèi)存,還有待抓取URL,已抓取URL還保存在內(nèi)存中的html等等消耗的內(nèi)存。

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

一個(gè)取巧的辦法是截?cái)郩RL。只把URL:https://www.tianyancha.com/company/23402373

的后綴:23402373放進(jìn)set()里,23402373只占8個(gè)字節(jié),一億個(gè)URL占700多M內(nèi)存。

但是如果你是用的野云主機(jī),用來不斷撥號用的非正規(guī)云主機(jī),這700多M內(nèi)存也是吃不消的,機(jī)器會非??ā?br/>

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

BloomFilter調(diào)用也非常簡單,當(dāng)然需要先install 安裝bloom_filter:

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

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

 三、反抓取訪問頻率限制

單臺機(jī)器,單個(gè)IP大家都明白,短時(shí)間內(nèi)訪問一個(gè)網(wǎng)站幾十次后肯定會被屏蔽的。每個(gè)網(wǎng)站對IP的解封策略也不一樣,有的1小時(shí)候后又能重新訪問,有的要一天,有的要幾個(gè)月去了。突破抓取頻率限制有兩種方式,一種是研究網(wǎng)站的反爬策略。有的網(wǎng)站不對列表頁做頻率控制,只對詳情頁控制。有的針對特定UA,referer,或者微信的H5頁面的頻率控制要弱很多。

另一種方式就是多IP抓取,多IP抓取又分IP代理池和adsl撥號兩種,這里說adsl撥號的方式。

adsl的特點(diǎn)是可以短時(shí)間內(nèi)重新?lián)芴柷袚QIP,IP被禁止了重新?lián)芴栆幌戮涂梢粤?。這樣你就可以開足馬力瘋狂抓取了,但是一天只有24小時(shí)合86400秒,要如何一天抓過百萬網(wǎng)頁,讓網(wǎng)絡(luò)性能最大化也是需要下一些功夫的,后面我再詳說。

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

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

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

四、網(wǎng)絡(luò)性能,抓取技術(shù)細(xì)節(jié)調(diào)優(yōu)

上面步驟做完了,每天能達(dá)到抓取五萬網(wǎng)頁的樣子,要達(dá)到百萬級規(guī)模,還需把網(wǎng)絡(luò)性能和抓取技術(shù)細(xì)節(jié)調(diào)優(yōu)。

1.調(diào)試開多少個(gè)線程,多長時(shí)間撥號切換IP一次最優(yōu)。

每個(gè)網(wǎng)站對短時(shí)間內(nèi)訪問次數(shù)的屏蔽策略不一樣,這需要實(shí)際測試,找出抓取效率最大化的時(shí)間點(diǎn)。先開一個(gè)線程,一直抓取到IP被屏蔽,記錄下抓取耗時(shí),總抓取次數(shù),和成功抓取次數(shù)。 再開2個(gè)線程,重復(fù)上面步驟,記錄抓取耗時(shí),總的和成功的抓取次數(shù)。再開4個(gè)線程,重復(fù)上面步驟。

2.requests請求優(yōu)化

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

3.優(yōu)化adsl撥號等待時(shí)間

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

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

而且 os.popen(‘rasdial 網(wǎng)絡(luò)名稱 adsl賬號名 adsl密碼’) 撥號完成后,你還不能馬上使用,那時(shí)外網(wǎng)還是不可用的,你需要檢測一下外網(wǎng)是否聯(lián)通。

我使用 ping 功能來檢測外網(wǎng)連通性:

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

code為0時(shí)表示聯(lián)通,不為0時(shí)還要重新?lián)芴?。而ping也很耗時(shí)間的,一個(gè)ping命令會ping 4次,就要耗時(shí)4秒。

知識Tips:

1.為什么不用異步抓?。?/strong>

沒必要,這里的整個(gè)抓取關(guān)鍵是網(wǎng)絡(luò)性能,而不是程序性能。用異步把程序性能提高了,單位時(shí)間的抓取次數(shù)是提高了,但是這樣反而會擊中對方網(wǎng)站的訪問頻率控制策略

2.要計(jì)算對方的帶寬壓力

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

一個(gè)中小型網(wǎng)站的帶寬在5M以內(nèi),大一點(diǎn)的網(wǎng)站帶寬可能10-30M,超大型的另算。

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

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

以上是Python爬蟲一天抓取百萬張網(wǎng)頁的方法是什么的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI