亚洲国产精品无码久久大片,亚洲AV无码乱码麻豆精品国产,亚洲品质自拍网站,少妇伦子伦精品无码STYLES,国产精久久久久久久

爬蟲(chóng)技術(shù)淺析

優(yōu)采云 發(fā)布時(shí)間: 2020-05-02 08:09

  

  談到爬蟲(chóng)構架,不得不提的是Scrapy的爬蟲(chóng)構架。Scrapy,是Python開(kāi)發(fā)的一個(gè)快速,高層次的爬蟲(chóng)框架,用于抓取web站點(diǎn)并從頁(yè)面中提取結構化的數據。Scrapy用途廣泛,可以用于數據挖掘、監測和自動(dòng)化測試。Scrapy吸引人的地方在于它是一個(gè)框架,任何人都可以依照需求便捷的更改。它也提供了多種類(lèi)型爬蟲(chóng)的子類(lèi),如BaseSpider、sitemap爬蟲(chóng)等。

  上圖是Scrapy的構架圖,綠線(xiàn)是數據流向,首先從初始URL 開(kāi)始,Scheduler 會(huì )將其交給 Downloader 進(jìn)行下載,下載以后會(huì )交給 Spider 進(jìn)行剖析,需要保存的數據則會(huì )被送到Item Pipeline,那是對數據進(jìn)行后期處理。另外,在數據流動(dòng)的通道里還可以安裝各類(lèi)中間件,進(jìn)行必要的處理。 因此在開(kāi)發(fā)爬蟲(chóng)的時(shí)侯,最好也先規劃好各類(lèi)模塊。我的做法是單獨規劃下載模塊,爬行模塊,調度模塊,數據儲存模塊。

  頁(yè)面下載分為靜態(tài)和動(dòng)態(tài)兩種下載形式。

  傳統爬蟲(chóng)借助的是靜態(tài)下載形式,靜態(tài)下載的優(yōu)勢是下載過(guò)程快,但是頁(yè)面只是一個(gè)無(wú)趣的html,因此頁(yè)面鏈接剖析中獲取的只是< a >標簽的href屬性或則大神可以自己剖析js,form之類(lèi)的標簽捕獲一些鏈接。在python中可以借助urllib2模塊或requests模塊實(shí)現功能。 動(dòng)態(tài)爬蟲(chóng)在web2.0時(shí)代則有特殊的優(yōu)勢,由于網(wǎng)頁(yè)會(huì )使用javascript處理,網(wǎng)頁(yè)內容通過(guò)Ajax異步獲取。所以,動(dòng)態(tài)爬蟲(chóng)須要剖析經(jīng)過(guò)javascript處理和ajax獲取內容后的頁(yè)面。目前簡(jiǎn)單的解決方式是通過(guò)基于webkit的模塊直接處理。PYQT4、Splinter和Selenium這三個(gè)模塊都可以達到目的。對于爬蟲(chóng)而言,瀏覽器界面是不需要的,因此使用一個(gè)headless browser是十分實(shí)惠的,HtmlUnit和phantomjs都是可以使用的headless browser。

  

  以上這段代碼是訪(fǎng)問(wèn)新浪網(wǎng)主站。通過(guò)對比靜態(tài)抓取頁(yè)面和動(dòng)態(tài)抓取頁(yè)面的厚度和對比靜態(tài)抓取頁(yè)面和動(dòng)態(tài)抓取頁(yè)面內抓取的鏈接個(gè)數。

  

  在靜態(tài)抓取中,頁(yè)面的寬度是563838,頁(yè)面內抓取的鏈接數目只有166個(gè)。而在動(dòng)態(tài)抓取中,頁(yè)面的寬度下降到了695991,而鏈接數達到了1422,有了逾10倍的提高。

  抓鏈接表達式

  正則:re.compile("href=\"([^\"]*)\"")

  Xpath:xpath('//*[@href]')

  頁(yè)面解析是實(shí)現抓取頁(yè)面內鏈接和抓取特定數據的模塊,頁(yè)面解析主要是對字符串的處理,而html是一種特殊的字符串,在Python中re、beautifulsoup、HTMLParser、lxml等模塊都可以解決問(wèn)題。對于鏈接,主要抓取a標簽下的href屬性,還有其他一些標簽的src屬性。

  URL去重是爬蟲(chóng)運行中一項關(guān)鍵的步驟,由于運行中的爬蟲(chóng)主要阻塞在網(wǎng)路交互中,因此防止重復的網(wǎng)路交互至關(guān)重要。爬蟲(chóng)通常會(huì )將待抓取的URL置于一個(gè)隊列中,從抓取后的網(wǎng)頁(yè)中提取到新的URL,在她們被裝入隊列之前,首先要確定這種新的URL沒(méi)有被抓取過(guò),如果之前早已抓取過(guò)了,就不再裝入隊列了。

  Hash表

  利用hash表做去重操作通常是最容易想到的方式,因為hash表查詢(xún)的時(shí)間復雜度是O(1),而且在hash表足夠大的情況下,hash沖突的機率就顯得太小,因此URL是否重復的判定準確性就十分高。利用hash表去重的這個(gè)做法是一個(gè)比較簡(jiǎn)單的解決方式。但是普通hash表也有顯著(zhù)的缺陷爬蟲(chóng)技術(shù),在考慮顯存的情況下,使用一張大的hash表是不妥的。Python中可以使用字典這一數據結構。

  URL壓縮

  如果hash表中,當每位節點(diǎn)存儲的是一個(gè)str方式的具體URL,是十分占用顯存的,如果把這個(gè)URL進(jìn)行壓縮成一個(gè)int型變量,內存占用程度上便有了3倍以上的縮小。因此可以借助Python的hashlib模塊來(lái)進(jìn)行URL壓縮。 思路:把hash表的節點(diǎn)的數據結構設置為集合,集合內貯存壓縮后的URL。

  Bloom Filter

  Bloom Filter是通過(guò)很少的錯誤換取了儲存空間的極大節約。Bloom Filter 是通過(guò)一組k 個(gè)定義在n 個(gè)輸入key 上的Hash Function,將上述n 個(gè)key 映射到m 位上的數據容器。

  

  上圖太清楚的說(shuō)明了Bloom Filter的優(yōu)勢,在可控的容器寬度內,所有hash函數對同一個(gè)元素估算的hash值都為1時(shí),就判定這個(gè)元素存在。 Python中hashlib,自帶多種hash函數,有MD5,sha1,sha224,sha256,sha384,sha512。代碼中還可以進(jìn)行加水處理,還是很方便的。 Bloom Filter也會(huì )形成沖突的情況,具體內容查看文章結尾的參考文章。

  在Python編程過(guò)程中,可以使用jaybaird提供的BloomFilter插口,或者自己造輪子。

  小細節

  有個(gè)小細節,在構建hash表的時(shí)侯選擇容器很重要。hash表占用空間很大是個(gè)太不爽的問(wèn)題,因此針對爬蟲(chóng)去重,下列方式可以解決一些問(wèn)題。

  

  上面這段代碼簡(jiǎn)單驗證了生成容器的運行時(shí)間。

  

  由上圖可以看出,建立一個(gè)寬度為1億的容器時(shí),選擇list容器程序的運行時(shí)間耗費了7.2s,而選擇字符串作為容器時(shí),才耗費了0.2s的運行時(shí)間。

  接下來(lái)瞧瞧顯存的占用情況。

  

  如果構建1億的列表占用了794660k顯存。

  

  而構建1億寬度的字符串卻占用了109720k顯存,空間占用大概降低了700000k。

  初級算法

  對于URL相似性,我只是實(shí)踐一個(gè)十分簡(jiǎn)單的技巧。

  在保證不進(jìn)行重復爬去的情況下,還須要對類(lèi)似的URL進(jìn)行判定。我采用的是sponge和ly5066113提供的思路。具體資料在參考文章里。

  下列是一組可以判定為相像的URL組

  按照預期,以上URL歸并后應當為

  思路如下,需要提取如下特點(diǎn)

  1,host字符串

  2,目錄深度(以’/’分割)

  3,尾頁(yè)特點(diǎn)

  具體算法

  

  算法本身太菜,各位一看才能懂。

  實(shí)際療效:

  

  上圖顯示了把8個(gè)不一樣的url,算出了2個(gè)值。通過(guò)實(shí)踐,在一張千萬(wàn)級的hash表中,沖突的情況是可以接受的。

  Python中的并發(fā)操作主要涉及的模型有:多線(xiàn)程模型、多進(jìn)程模型、協(xié)程模型。Elias專(zhuān)門(mén)寫(xiě)了一篇文章爬蟲(chóng)技術(shù),來(lái)比較常用的幾種模型并發(fā)方案的性能。對于爬蟲(chóng)本身來(lái)說(shuō),限制爬蟲(chóng)速率主要來(lái)自目標服務(wù)器的響應速率,因此選擇一個(gè)控制上去順手的模塊才是對的。

  多線(xiàn)程模型,是最容易上手的,Python中自帶的threading模塊能挺好的實(shí)現并發(fā)需求,配合Queue模塊來(lái)實(shí)現共享數據。

  多進(jìn)程模型和多線(xiàn)程模型類(lèi)似,multiprocessing模塊中也有類(lèi)似的Queue模塊來(lái)實(shí)現數據共享。在linux中,用戶(hù)態(tài)的進(jìn)程可以借助多核心的優(yōu)勢,因此在多核背景下,能解決爬蟲(chóng)的并發(fā)問(wèn)題。

  協(xié)程模型,在Elias的文章中,基于greenlet實(shí)現的解釋器程序的性能僅次于Stackless Python,大致比Stackless Python慢一倍,比其他方案快接近一個(gè)數量級。因此基于gevent(封裝了greenlet)的并發(fā)程序會(huì )有挺好的性能優(yōu)勢。

  具體說(shuō)明下gevent(非阻塞異步IO)。,“Gevent是一種基于解釋器的Python網(wǎng)絡(luò )庫,它用到Greenlet提供的,封裝了libevent風(fēng)波循環(huán)的高層同步API?!?/p>

  從實(shí)際的編程療效來(lái)看,協(xié)程模型確實(shí)表現非常好,運行結果的可控性顯著(zhù)強了不少, gevent庫的封裝易用性極強。

  數據儲存本身設計的技術(shù)就十分多,作為小菜不敢亂說(shuō),但是工作還是有一些小經(jīng)驗是可以分享的。

  前提:使用關(guān)系數據庫,測試中選擇的是mysql,其他類(lèi)似sqlite,SqlServer思路上沒(méi)有區別。

  當我們進(jìn)行數據儲存時(shí),目的就是降低與數據庫的交互操作,這樣可以增強性能。通常情況下,每當一個(gè)URL節點(diǎn)被讀取,就進(jìn)行一次數據儲存,對于這樣的邏輯進(jìn)行無(wú)限循環(huán)。其實(shí)這樣的性能體驗是十分差的,存儲速率特別慢。

  進(jìn)階做法,為了減輕與數據庫的交互次數,每次與數據庫交互從之前傳送1個(gè)節點(diǎn)弄成傳送10個(gè)節點(diǎn),到傳送100個(gè)節點(diǎn)內容,這樣效率變有了10倍至100倍的提高,在實(shí)際應用中,效果是非常好的。:D

  爬蟲(chóng)模型

  

  目前這個(gè)爬蟲(chóng)模型如上圖,調度模塊是核心模塊。調度模塊分別與下載模塊,析取模塊,存儲模塊共享三個(gè)隊列,下載模塊與析取模塊共享一個(gè)隊列。數據傳遞方向如圖示。

0 個(gè)評論

要回復文章請先登錄注冊


官方客服QQ群

微信人工客服

QQ人工客服


線(xiàn)

亚洲国产精品无码久久大片,亚洲AV无码乱码麻豆精品国产,亚洲品质自拍网站,少妇伦子伦精品无码STYLES,国产精久久久久久久