小編給大家分享一下Python爬蟲一天抓取百萬張網(wǎng)頁的方法是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
員工經(jīng)過長期磨合與沉淀,具備了協(xié)作精神,得以通過團隊的力量開發(fā)出優(yōu)質(zhì)的產(chǎn)品。創(chuàng)新互聯(lián)建站堅持“專注、創(chuàng)新、易用”的產(chǎn)品理念,因為“專注所以專業(yè)、創(chuàng)新互聯(lián)網(wǎng)站所以易用所以簡單”。公司專注于為企業(yè)提供成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計、微信公眾號開發(fā)、電商網(wǎng)站開發(fā),重慶小程序開發(fā),軟件按需網(wǎng)站策劃等一站式互聯(lián)網(wǎng)企業(yè)服務。
一、優(yōu)化硬盤存儲
所以千萬級網(wǎng)頁的抓取是需要先設(shè)計的,先來做一個計算題。共要抓取一億張頁面,一般一張網(wǎng)頁的大小是400KB左右,一億張網(wǎng)頁就是1億X200KB=36TB 。這么大的存儲需求,一般的電腦和硬盤都是沒法存儲的。所以肯定要對網(wǎng)頁做壓縮后存儲,可以用zlib壓縮,也可以用壓縮率更好的bz2或pylzma 。
二、優(yōu)化內(nèi)存,URL去重
再來說內(nèi)存占用問題,做爬蟲程序為了防止重復抓取URL,一般要把URL都加載進內(nèi)存里,放在set()里面。拿天眼查的URL舉例:
https://www.tianyancha.com/company/23402373
這個完整URL有44個字節(jié),一億個URL就是4G,一億個URL就要占用4G內(nèi)存,這還沒有算存這一億個URL需要的數(shù)據(jù)結(jié)構(gòu)內(nèi)存,還有待抓取URL,已抓取URL還保存在內(nèi)存中的html等等消耗的內(nèi)存。
所以這樣直接用set()保存URL是不建議的,除非你的內(nèi)存有十幾個G。
一個取巧的辦法是截斷URL。只把URL:https://www.tianyancha.com/company/23402373
的后綴:23402373放進set()里,23402373只占8個字節(jié),一億個URL占700多M內(nèi)存。
但是如果你是用的野云主機,用來不斷撥號用的非正規(guī)云主機,這700多M內(nèi)存也是吃不消的,機器會非常卡。
就還需要想辦法壓縮URL的內(nèi)存占用,可以使用BloomFilter算法,是一個很經(jīng)典的算法,非常適用海量數(shù)據(jù)的排重過濾,占用極少的內(nèi)存,查詢效率也非常的高。它的原理是把一個字符串映射到一個bit上,剛才23402373占8個字節(jié),現(xiàn)在只占用1個bit(1字節(jié)=8bit),內(nèi)存節(jié)省了近64倍,以前700M內(nèi)存,現(xiàn)在只需要10多M了。
BloomFilter調(diào)用也非常簡單,當然需要先install 安裝bloom_filter:
from bloom_filter import BloomFilter # 生成一個裝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是否重復,我用的__contains__()方法,也可能是我沒用對,不過判重效果是一樣的。
三、反抓取訪問頻率限制
單臺機器,單個IP大家都明白,短時間內(nèi)訪問一個網(wǎng)站幾十次后肯定會被屏蔽的。每個網(wǎng)站對IP的解封策略也不一樣,有的1小時候后又能重新訪問,有的要一天,有的要幾個月去了。突破抓取頻率限制有兩種方式,一種是研究網(wǎng)站的反爬策略。有的網(wǎng)站不對列表頁做頻率控制,只對詳情頁控制。有的針對特定UA,referer,或者微信的H5頁面的頻率控制要弱很多。
另一種方式就是多IP抓取,多IP抓取又分IP代理池和adsl撥號兩種,這里說adsl撥號的方式。
adsl的特點是可以短時間內(nèi)重新?lián)芴柷袚QIP,IP被禁止了重新?lián)芴栆幌戮涂梢粤?。這樣你就可以開足馬力瘋狂抓取了,但是一天只有24小時合86400秒,要如何一天抓過百萬網(wǎng)頁,讓網(wǎng)絡(luò)性能最大化也是需要下一些功夫的,后面我再詳說。
至于有哪些可以adsl撥號的野云主機,你在百度搜”vps adsl”,能選擇的廠商很多的。大多宣稱有百萬級IP資源可撥號,我曾測試過一段時間,把每次撥號的IP記錄下來,有真實二三十萬IP的就算不錯了。
選adsl的一個注意事項是,有的廠商撥號IP只能播出C段和D段IP,110(A段).132(B段).3(C段).2(D段),A和B段都不會變,靠C,D段IP高頻次抓取對方網(wǎng)站,有可能對方網(wǎng)站把整個C/D段IP都封掉。
C/D段加一起255X255就是6萬多個IP全都報廢,所以要選撥號IP范圍較寬的廠商。 你要問我哪家好,我也不知道,這些都是野云主機,質(zhì)量和穩(wěn)定性本就沒那么好。只有多試一試,試的成本也不大,買一臺玩玩一個月也就一百多元,還可以按天買。
四、網(wǎng)絡(luò)性能,抓取技術(shù)細節(jié)調(diào)優(yōu)
上面步驟做完了,每天能達到抓取五萬網(wǎng)頁的樣子,要達到百萬級規(guī)模,還需把網(wǎng)絡(luò)性能和抓取技術(shù)細節(jié)調(diào)優(yōu)。
1.調(diào)試開多少個線程,多長時間撥號切換IP一次最優(yōu)。
每個網(wǎng)站對短時間內(nèi)訪問次數(shù)的屏蔽策略不一樣,這需要實際測試,找出抓取效率最大化的時間點。先開一個線程,一直抓取到IP被屏蔽,記錄下抓取耗時,總抓取次數(shù),和成功抓取次數(shù)。 再開2個線程,重復上面步驟,記錄抓取耗時,總的和成功的抓取次數(shù)。再開4個線程,重復上面步驟。
2.requests請求優(yōu)化
要優(yōu)化requests.get(timeout=1.5)的超時時間,不設(shè)置超時的話,有可能get()請求會一直掛起等待。而且野云主機本身性能就不穩(wěn)定,長時間不回請求很正常。如果要追求抓取效率,超時時間設(shè)置短一點,設(shè)置10秒超時完全沒有意義。對于超時請求失敗的,大不了以后再二次請求,也比設(shè)置10秒的抓取效率高很多。
3.優(yōu)化adsl撥號等待時間
上面步驟已算把單臺機器的抓取技術(shù)問題優(yōu)化到一個高度了,還剩一個優(yōu)化野云主機的問題。就是每次斷開撥號后,要等待幾秒鐘再撥號,太短時間內(nèi)再撥號有可能又撥到上一個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密碼’) 撥號完成后,你還不能馬上使用,那時外網(wǎng)還是不可用的,你需要檢測一下外網(wǎng)是否聯(lián)通。
我使用 ping 功能來檢測外網(wǎng)連通性:
import os code = os.system('ping www.baidu.com')
code為0時表示聯(lián)通,不為0時還要重新?lián)芴?。而ping也很耗時間的,一個ping命令會ping 4次,就要耗時4秒。
知識Tips:
1.為什么不用異步抓?。?/strong>
沒必要,這里的整個抓取關(guān)鍵是網(wǎng)絡(luò)性能,而不是程序性能。用異步把程序性能提高了,單位時間的抓取次數(shù)是提高了,但是這樣反而會擊中對方網(wǎng)站的訪問頻率控制策略
2.要計算對方的帶寬壓力
抓取歸抓取,但不要影響對方網(wǎng)站,把對方網(wǎng)站帶寬都打滿了。
一個中小型網(wǎng)站的帶寬在5M以內(nèi),大一點的網(wǎng)站帶寬可能10-30M,超大型的另算。
一張網(wǎng)頁300KB,對方一般會壓縮后傳輸給瀏覽器,就按壓縮后30KB算,你的爬蟲一秒請求20次,帶寬就是600KB??赡芤粋€網(wǎng)站每天都有幾十個爬蟲都在爬,我們按有10個爬蟲在同時抓取,就是這些爬蟲一秒內(nèi)就要消耗600KBX10=6M帶寬。
再加上還有正規(guī)爬蟲,人家網(wǎng)站上的正常用戶訪問這些,算下來可能一共要消耗10M帶寬。一般的大中型網(wǎng)站都是吃不消的。
以上是Python爬蟲一天抓取百萬張網(wǎng)頁的方法是什么的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!