大家好!回顧上一期,我們?cè)诮榻B了爬蟲的基本概念之后,就利用各種工具橫沖直撞的完成了一個(gè)小爬蟲,目的就是猛、糙、快,方便初學(xué)者上手,建立信心。對(duì)于有一定基礎(chǔ)的讀者,請(qǐng)不要著急,以后我們會(huì)學(xué)習(xí)主流的開源框架,打造出一個(gè)強(qiáng)大專業(yè)的爬蟲系統(tǒng)!不過(guò)在此之前,要繼續(xù)打好基礎(chǔ),本期我們先介紹爬蟲的種類,然后選取最典型的通用網(wǎng)絡(luò)爬蟲,為其設(shè)計(jì)一個(gè)迷你框架。有了自己對(duì)框架的思考后,再學(xué)習(xí)復(fù)雜的開源框架就有頭緒了。
“真誠(chéng)服務(wù),讓網(wǎng)絡(luò)創(chuàng)造價(jià)值”是我們的服務(wù)理念,創(chuàng)新互聯(lián)公司團(tuán)隊(duì)十多年如一日始終堅(jiān)持在網(wǎng)站建設(shè)領(lǐng)域,為客戶提供優(yōu)質(zhì)服。不管你處于什么行業(yè),助你輕松跨入“互聯(lián)網(wǎng)+”時(shí)代,PC網(wǎng)站+手機(jī)網(wǎng)站+公眾號(hào)+微信小程序定制開發(fā)。今天我們會(huì)把更多的時(shí)間用在思考上,而不是一根筋的coding。用80%的時(shí)間思考,20%的時(shí)間敲鍵盤,這樣更有利于進(jìn)步。
語(yǔ)言:帶足彈藥,繼續(xù)用Python開路!
threading:threading庫(kù)可以在單獨(dú)的線程中執(zhí)行任何的在Python中可以調(diào)用的對(duì)象。Python 2.x中的thread模塊已被廢棄,用戶可以使用threading模塊代替。在Python 3中不能再使用thread模塊。為了兼容性,Python 3將thread重命名為_thread。
queue:queue模塊中提供了同步的、線程安全的隊(duì)列類,包括FIFO(先入先出)隊(duì)列Queue,LIFO(后入先出)隊(duì)列LifoQueue,和優(yōu)先級(jí)隊(duì)列PriorityQueue。這些隊(duì)列都實(shí)現(xiàn)了鎖原語(yǔ),能夠在多線程中直接使用??梢允褂藐?duì)列來(lái)實(shí)現(xiàn)線程間的同步。
re:Python 自1.5版本起增加了re模塊,它提供Perl風(fēng)格的正則表達(dá)式模式。re模塊使 Python語(yǔ)言擁有全部的正則表達(dá)式功能。
argparse:Python用于解析命令行參數(shù)和選項(xiàng)的標(biāo)準(zhǔn)模塊,用于代替已經(jīng)過(guò)時(shí)的optparse模塊。argparse模塊的作用是用于解析命令行參數(shù)。
configparser:讀取配置文件的模塊。
網(wǎng)絡(luò)爬蟲按照系統(tǒng)結(jié)構(gòu)和實(shí)現(xiàn)技術(shù),大致可以分為以下幾種類型:通用網(wǎng)絡(luò)爬蟲(General Purpose Web Crawler)、聚焦網(wǎng)絡(luò)爬蟲(Focused Web Crawler)、增量式網(wǎng)絡(luò)爬蟲(Incremental Web Crawler)、深層網(wǎng)絡(luò)爬蟲(Deep Web Crawler)。實(shí)際的網(wǎng)絡(luò)爬蟲系統(tǒng)通常是幾種爬蟲技術(shù)相結(jié)合實(shí)現(xiàn)的。
通用網(wǎng)絡(luò)爬蟲
通用網(wǎng)絡(luò)爬蟲又稱全網(wǎng)爬蟲(Scalable Web Crawler),爬取對(duì)象從一些種子 URL 擴(kuò)充到整個(gè) Web。主要為門戶站點(diǎn)搜索引擎和大型 Web 服務(wù)提供商采集數(shù)據(jù)。
通用網(wǎng)絡(luò)爬蟲的結(jié)構(gòu)大致可以分為頁(yè)面爬取模塊 、頁(yè)面分析模塊、鏈接過(guò)濾模塊、頁(yè)面存儲(chǔ)模塊、URL 隊(duì)列、初始 URL 集合幾個(gè)部分。為提高工作效率,通用網(wǎng)絡(luò)爬蟲會(huì)采取一定的爬取策略。 常用的爬取策略有:深度優(yōu)先策略、廣度優(yōu)先策略。
1) 深度優(yōu)先策略(DFS):其基本方法是按照深度由低到高的順序,依次訪問(wèn)下一級(jí)網(wǎng)頁(yè)鏈接,直到不能再深入為止。
2) 廣度優(yōu)先策略(BFS):此策略按照網(wǎng)頁(yè)內(nèi)容目錄層次深淺來(lái)爬取頁(yè)面,處于較淺目錄層次的頁(yè)面首先被爬取。 當(dāng)同一層次中的頁(yè)面爬取完畢后,爬蟲再深入下一層繼續(xù)爬取。
聚焦網(wǎng)絡(luò)爬蟲
聚焦網(wǎng)絡(luò)爬蟲(Focused Crawler),又稱主題網(wǎng)絡(luò)爬蟲(Topical Crawler),是指選擇性地爬取那些與預(yù)先定義好的主題相關(guān)頁(yè)面的網(wǎng)絡(luò)爬蟲。 和通用網(wǎng)絡(luò)爬蟲相比,聚焦爬蟲只需要爬取與主題相關(guān)的頁(yè)面,極大地節(jié)省了硬件和網(wǎng)絡(luò)資源,保存的頁(yè)面也由于數(shù)量少而更新快,還可以很好地滿足一些特定人群對(duì)特定領(lǐng)域信息的需求。我們之前爬的歌單就屬于這一種。
增量式網(wǎng)絡(luò)爬蟲
增量式網(wǎng)絡(luò)爬蟲(Incremental Web Crawler)是 指 對(duì) 已 下 載 網(wǎng) 頁(yè) 采 取 增 量式更新和只爬取新產(chǎn)生的或者已經(jīng)發(fā)生變化網(wǎng)頁(yè)的爬蟲,它能夠在一定程度上保證所爬取的頁(yè)面是盡可能新的頁(yè)面。 和周期性爬取和刷新頁(yè)面的網(wǎng)絡(luò)爬蟲相比,增量式爬蟲只會(huì)在需要的時(shí)候爬取新產(chǎn)生或發(fā)生更新的頁(yè)面 ,并不重新下載沒(méi)有發(fā)生變化的頁(yè)面,可有效減少數(shù)據(jù)下載量,及時(shí)更新已爬取的網(wǎng)頁(yè),減小時(shí)間和空間上的耗費(fèi),但是增加了爬取算法的復(fù)雜度和實(shí)現(xiàn)難度?,F(xiàn)在比較火的輿情爬蟲一般都是增量式網(wǎng)絡(luò)爬蟲。
深網(wǎng)爬蟲
Web 頁(yè)面按存在方式可以分為表層網(wǎng)頁(yè)(Surface Web)和深層網(wǎng)頁(yè)(Deep Web,也稱 Invisible Web Pages 或 Hidden Web)。 表層網(wǎng)頁(yè)是指?jìng)鹘y(tǒng)搜索引擎可以索引的頁(yè)面,以超鏈接可以到達(dá)的靜態(tài)網(wǎng)頁(yè)為主構(gòu)成的 Web 頁(yè)面。Deep Web 是那些大部分內(nèi)容不能通過(guò)靜態(tài)鏈接獲取的、隱藏在搜索表單后的,只有用戶提交一些關(guān)鍵詞才能獲得的 Web 頁(yè)面。例如那些用戶注冊(cè)后內(nèi)容才可見(jiàn)的網(wǎng)頁(yè)就屬于 Deep Web。
下面以比較典型的通用爬蟲為例,分析其工程要點(diǎn),設(shè)計(jì)并實(shí)現(xiàn)一個(gè)迷你框架。架構(gòu)圖如下:
代碼結(jié)構(gòu):
config_load.py 配置文件加載
crawl_thread.py 爬取線程
mini_spider.py 主線程
spider.conf 配置文件
url_table.py url隊(duì)列、url表
urls.txt 種子url集合
webpage_parse.py 網(wǎng)頁(yè)分析
webpage_save.py 網(wǎng)頁(yè)存儲(chǔ)
看看配置文件里有什么內(nèi)容:
spider.conf
Step 1. 采用BFS還是DFS?
理論上,這兩個(gè)算法都能夠在大致相同的時(shí)間里爬取整個(gè)互聯(lián)網(wǎng)上的內(nèi)容。但顯然各個(gè)網(wǎng)站最重要的網(wǎng)頁(yè)應(yīng)該是它的首頁(yè)。在極端情況下,如果只能下載非常有限的網(wǎng)頁(yè),那么應(yīng)該下載的所有網(wǎng)站的首頁(yè),如果把爬蟲再擴(kuò)大些,應(yīng)該爬取從首頁(yè)直接鏈接的網(wǎng)頁(yè),因?yàn)檫@些網(wǎng)頁(yè)是網(wǎng)站設(shè)計(jì)者自己認(rèn)為相當(dāng)重要的網(wǎng)頁(yè)。在這個(gè)前提下,顯然BFS明顯優(yōu)于DFS。事實(shí)上在搜索引擎的爬蟲里,主要采用的就是BFS。我們的框架采取這種策略。
抓取深度可以通過(guò)配置文件中的max_depth設(shè)置,只要沒(méi)到達(dá)指定深度,程序就會(huì)不停的將解析出的url放入隊(duì)列中:
mini_spider.py
Step 2. 初始URL集合、URL隊(duì)列
我們來(lái)看看通用爬蟲如何下載整個(gè)互聯(lián)網(wǎng)。假設(shè)從一家門戶網(wǎng)站的首頁(yè)出發(fā),先下載這個(gè)網(wǎng)頁(yè)(深度=0),然后通過(guò)分析這個(gè)網(wǎng)頁(yè),可以找到頁(yè)面里的所有超鏈接,也就等于知道了這家門戶網(wǎng)站首頁(yè)所直接連接的全部網(wǎng)頁(yè),諸如京東理財(cái)、京東白條,京東眾籌等(深度=1)。接下來(lái)訪問(wèn)、下載并分析京東理財(cái)?shù)染W(wǎng)頁(yè),又能找到其他相連的網(wǎng)頁(yè)(深度=2)。讓計(jì)算機(jī)不停的做下去,就能下載整個(gè)網(wǎng)站。
在這個(gè)過(guò)程中,我們需要一個(gè)“初始URL集合”保存門戶的首頁(yè),還需要一個(gè)“URL隊(duì)列”保存分析網(wǎng)頁(yè)得到的超鏈接。
mini_spider.py
url_table.py
Step 3. 記錄哪些網(wǎng)頁(yè)已經(jīng)下載過(guò)的小本本——URL表。
在互聯(lián)網(wǎng)上,一個(gè)網(wǎng)頁(yè)可能被多個(gè)網(wǎng)頁(yè)中的超鏈接所指向。這樣在遍歷互聯(lián)網(wǎng)這張圖的時(shí)候,這個(gè)網(wǎng)頁(yè)可能被多次訪問(wèn)到。為了防止一個(gè)網(wǎng)頁(yè)被下載和解析多次,需要一個(gè)URL表記錄哪些網(wǎng)頁(yè)已經(jīng)下載過(guò)。再遇到這個(gè)網(wǎng)頁(yè)的時(shí)候,我們就可以跳過(guò)它。
crawl_thread.py
Step 4. 多個(gè)抓取線程
為了提升爬蟲性能,需要多個(gè)抓取線程,從URL隊(duì)列獲取鏈接進(jìn)行處理。多線程并沒(méi)什么毛病,但Python的多線程可能會(huì)引起很多人的質(zhì)疑,這源于Python設(shè)計(jì)之初的考慮:GIL。GIL的全稱是Global Interpreter Lock(全局解釋器鎖),某個(gè)線程想要執(zhí)行,必須先拿到GIL,并且在一個(gè)Python進(jìn)程中,GIL只有一個(gè)。結(jié)果就是Python里一個(gè)進(jìn)程永遠(yuǎn)只能同時(shí)執(zhí)行一個(gè)線程,這就是為什么在多核CPU上,Python的多線程效率并不高。那么我們?yōu)槭裁催€要用Python多線程呢?
CPU密集型代碼(各種循環(huán)處理、編解碼等等),在這種情況下,由于計(jì)算工作多,ticks計(jì)數(shù)很快就會(huì)達(dá)到閾值,然后觸發(fā)GIL的釋放與再競(jìng)爭(zhēng)(多個(gè)線程來(lái)回切換當(dāng)然是需要消耗資源的),Python下的多線程對(duì)CPU密集型代碼并不友好。
IO密集型代碼(文件處理、網(wǎng)絡(luò)爬蟲等),多線程能夠有效提升效率(單線程下有IO操作會(huì)進(jìn)行IO等待,造成不必要的時(shí)間浪費(fèi),而開啟多線程能在線程A等待時(shí),自動(dòng)切換到線程B,可以不浪費(fèi)CPU的資源,從而能提升程序執(zhí)行效率)。Python的多線程對(duì)IO密集型代碼比較友好。
所以,對(duì)于IO密集的爬蟲程序,使用Python多線程是沒(méi)問(wèn)題的。
crawl_thread.py
Step 5. 頁(yè)面分析模塊
從網(wǎng)頁(yè)中解析出URLs或者其他有用的數(shù)據(jù)。這個(gè)是上期重點(diǎn)介紹的,可以參考之前的代碼。
Step 6. 頁(yè)面存儲(chǔ)模塊
保存頁(yè)面的模塊,目前將文件保存為文件,以后可以擴(kuò)展出多種存儲(chǔ)方式,如mysql,mongodb,hbase等等。
webpage_save.py
寫到這里,整個(gè)框架已經(jīng)清晰的呈現(xiàn)在大家眼前了,千萬(wàn)不要小看它,不管多么復(fù)雜的框架都是在這些基本要素上擴(kuò)展出來(lái)的。
下一步
基礎(chǔ)知識(shí)的學(xué)習(xí)暫時(shí)告一段落,希望能夠幫助大家打下一定的基礎(chǔ)。下期開始為大家介紹強(qiáng)大成熟的爬蟲框架Scrapy,它提供了很多強(qiáng)大的特性來(lái)使得爬取更為簡(jiǎn)單高效,更多精彩,敬請(qǐng)期待!
最后,初學(xué)者進(jìn)階的福音
想學(xué)習(xí),基礎(chǔ)不夠?沒(méi)關(guān)系,我們提供免費(fèi)提供VIP基礎(chǔ)學(xué)習(xí)課程,讓你快速入門,掌握Python!
有基礎(chǔ)的小伙伴想學(xué)習(xí)項(xiàng)目實(shí)戰(zhàn)?沒(méi)問(wèn)題,每晚八點(diǎn)都有博士大牛帶你學(xué)習(xí)操作項(xiàng)目!
只要你有一顆想學(xué)習(xí)的心,我們隨時(shí)歡迎~
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。