您好,登錄后才能下訂單哦!
小編給大家分享一下Python爬蟲一天抓取百萬張網頁的方法是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
一、優化硬盤存儲
所以千萬級網頁的抓取是需要先設計的,先來做一個計算題。共要抓取一億張頁面,一般一張網頁的大小是400KB左右,一億張網頁就是1億X200KB=36TB 。這么大的存儲需求,一般的電腦和硬盤都是沒法存儲的。所以肯定要對網頁做壓縮后存儲,可以用zlib壓縮,也可以用壓縮率更好的bz2或pylzma 。
二、優化內存,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內存也是吃不消的,機器會非常卡。
就還需要想辦法壓縮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添加URL bloom.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頁面的頻率控制要弱很多。
另一種方式就是多IP抓取,多IP抓取又分IP代理池和adsl撥號兩種,這里說adsl撥號的方式。
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范圍較寬的廠商。 你要問我哪家好,我也不知道,這些都是野云主機,質量和穩定性本就沒那么好。只有多試一試,試的成本也不大,買一臺玩玩一個月也就一百多元,還可以按天買。
四、網絡性能,抓取技術細節調優
上面步驟做完了,每天能達到抓取五萬網頁的樣子,要達到百萬級規模,還需把網絡性能和抓取技術細節調優。
1.調試開多少個線程,多長時間撥號切換IP一次最優。
每個網站對短時間內訪問次數的屏蔽策略不一樣,這需要實際測試,找出抓取效率最大化的時間點。先開一個線程,一直抓取到IP被屏蔽,記錄下抓取耗時,總抓取次數,和成功抓取次數。 再開2個線程,重復上面步驟,記錄抓取耗時,總的和成功的抓取次數。再開4個線程,重復上面步驟。
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秒。
知識Tips:
1.為什么不用異步抓取?
沒必要,這里的整個抓取關鍵是網絡性能,而不是程序性能。用異步把程序性能提高了,單位時間的抓取次數是提高了,但是這樣反而會擊中對方網站的訪問頻率控制策略
2.要計算對方的帶寬壓力
抓取歸抓取,但不要影響對方網站,把對方網站帶寬都打滿了。
一個中小型網站的帶寬在5M以內,大一點的網站帶寬可能10-30M,超大型的另算。
一張網頁300KB,對方一般會壓縮后傳輸給瀏覽器,就按壓縮后30KB算,你的爬蟲一秒請求20次,帶寬就是600KB。可能一個網站每天都有幾十個爬蟲都在爬,我們按有10個爬蟲在同時抓取,就是這些爬蟲一秒內就要消耗600KBX10=6M帶寬。
再加上還有正規爬蟲,人家網站上的正常用戶訪問這些,算下來可能一共要消耗10M帶寬。一般的大中型網站都是吃不消的。
以上是Python爬蟲一天抓取百萬張網頁的方法是什么的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。