分布式爬蟲原理簡單介紹


 

1.在了解分布式爬蟲之前先看看爬蟲流程會好理解一些

1.1 爬蟲算法流程

 

1.2 scrapy框架簡介

Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。可以應用在包括數據挖掘,

信息處理或存儲歷史數據等一系列的程序中。其最初是為了頁面抓取 (更確切來說, 網絡抓取 )所設計的,

也可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。

Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試。

1.2.1 scrapy流程圖

 

 

1.3 分布式爬蟲概念

由於需要爬取的數據量大,任務多,一台機器效率太低,需要多台機器共同協作處理。分布式爬蟲將多台主機組合起來, 共同完成一個爬取任務,快速高效地提高爬取效率。

分布式爬蟲可以分為若干個分布式層級,不同的應用可能由其中部分層級構成。

大型分布式爬蟲主要分為以下3個層級:分布式數據中心、分布式抓取服務器及分布式爬蟲程序。整個爬蟲系統由全球多個分布式數據中心共同組成,每個數據中心又由多台高速網絡連接的抓取服務器構成,而每台服務器又可以部署多個爬蟲程序。通過多層級的分布式爬蟲體系,才可能保證抓取數據的及時性和全面性。

 

分布式爬蟲流

 

 

 

 

 

 

 

 

 

 兩者的比較來看后者多了一個redis組件,主要影響兩個地方:第一個是調度器。第二個是數據的處理。

 

分布式策略圖

 

 

 

作為一個分布式爬蟲,是需要有一個Master端(核心服務器)的,在Master端,會搭建一個數據庫,用來存儲start_urls、request、items。Master的職責是負責url指紋判重,Request的分配,以及數據的存儲(一般在Master端會安裝一個mongodb用來存儲items)。出了Master之外,還有一個角色就是slaver(爬蟲程序執行端),它主要負責執行爬蟲程序爬取數據,並將爬取過程中新的Request提交到Master的數據庫中。

如上圖,假設我們有四台電腦:A, B, C, D ,其中任意一台電腦都可以作為 Master端 或 Slaver端。整個流程是: 

  1. 首先Slaver端從Master端拿任務(Request、url)進行數據抓取,Slaver抓取數據的同時,產生新任務的Request便提交給 Master 處理;
  2. Master端只有一個數據庫,負責將未處理的Request去重和任務分配,將處理后的Request加入待爬隊列,並且存儲爬取的數據。

 

1.4scrapy-redis

 由上面的流程圖可知,光靠scrapy是完成不了分布式任務的,還需要用到redis配合,而其中就需要scrapy-redis這個依賴。

 

pip isntall scrapy-redis #這個包不大,如果你實在下不動,加‘-i’參數換個國內源

 

2.拓展組件

scrapy-redis在scrapy的架構上增加了redis,基於redis的特性拓展了如下四種組件:Scheduler,Duplication Filter,Item Pipeline,Base Spider。

 

4.1 Scheduler(新的調度器)

scrapy改造了python本來的collection.deque(雙向隊列)形成了自己的Scrapy queue,但是Scrapy多個spider不能共享待爬取隊列Scrapy queue,即Scrapy本身不支持爬蟲分布式,scrapy-redis 的解決是把這個Scrapy queue換成redis數據庫(也是指redis隊列),從同一個redis-server存放要爬取的request,便能讓多個spider去同一個數據庫里讀取。

Scrapy中跟“待爬隊列”直接相關的就是調度器Scheduler,它負責對新的request進行入列操作(加入Scrapy queue),取出下一個要爬取的request(從Scrapy queue中取出)等操作。它把待爬隊列按照優先級建立了一個字典結構,然后根據request中的優先級,來決定該入哪個隊列,出列時則按優先級較小的優先出列。為了管理這個比較高級的隊列字典,Scheduler需要提供一系列的方法。但是原來的Scheduler已經無法使用,所以使用Scrapy-redis的scheduler組件。

4.2 Duplication Filter(指紋去重)

Scrapy中用集合set( )實現這個request去重功能,Scrapy中把已經發送的request指紋放入到一個集合中,把下一個request的指紋拿到集合中比對,如果該指紋存在於集合中,說明這個request發送過了,如果沒有則繼續操作。

scrapy-redis中去重是由Duplication Filter組件來實現的,它通過redis的set不重復的特性,巧妙的實現了DuplicationFilter去重。scrapy-redis調度器從引擎接受request,將request的指紋存入redis的set檢查是否重復,並將不重復的request push寫入redis的 request queue。引擎請求request(Spider發出的)時,調度器從redis的request queue隊列里根據優先級pop 出⼀個request 返回給引擎,引擎將此request發給spider處理。

4.3 Item Pipeline

引擎將(Spider返回的)爬取到的Item給Item Pipeline,scrapy-redis 的Item Pipeline將爬取到的 Item 存入redis的 items queue。修改過Item Pipeline可以很方便的根據 key 從 items queue 提取item,從而實現 items processes集群。

4.4 Base Spider

不在使用scrapy原有的Spider類,重寫的RedisSpider繼承了Spider和RedisMixin這兩個類,RedisMixin是用來從redis讀取url的類。

當我們生成一個Spider繼承RedisSpider時,調用setup_redis函數,這個函數會去連接redis數據庫,然后會設置signals(信號):一個是當spider空閑時候的signal,會調用spider_idle函數,這個函數調用schedule_next_request函數,保證spider是一直活着的狀態,並且拋出DontCloseSpider異常。一個是當抓到一個item時的signal,會調用item_scraped函數,這個函數會調用schedule_next_request函數,獲取下一個request。

4.5 總結 

這套組件通過重寫scheduler和spider類,實現了調度、spider啟動和redis的交互;

實現新的dupefilter和queue類,達到了判重和調度容器和redis的交互,因為每個主機上的爬蟲進程都訪問同一個redis數據庫,所以調度和判重都統一進行統一管理,達到了分布式爬蟲的目的;當spider被初始化時,同時會初始化一個對應的scheduler對象,這個調度器對象通過讀取settings,配置好自己的調度容器queue和判重工具dupefilter;

每當一個spider產出一個request的時候,scrapy引擎會把這個reuqest遞交給這個spider對應的scheduler對象進行調度,scheduler對象通過訪問redis對request進行判重,如果不重復就把他添加進redis中的調度器隊列里。當調度條件滿足時,scheduler對象就從redis的調度器隊列中取出一個request發送給spider,讓他爬取;

當spider爬取的所有暫時可用url之后,scheduler發現這個spider對應的redis的調度器隊列空了,於是觸發信號spider_idle,spider收到這個信號之后,直接連接redis讀取strart_url池,拿去新的一批url入口,然后再次重復上邊的工作。

4.6 優缺點

Slaver端從Master端拿任務(Request/url/ID)進行數據抓取,在抓取數據的同時也生成新任務,並將任務拋給Master。Master端只有一個Redis數據庫,負責對Slaver提交的任務進行去重、加入待爬隊列。

優點:scrapy-redis默認使用的就是這種策略,我們實現起來很簡單,因為任務調度等工作scrapy-redis都已經幫我們做好了,我們只需要繼承RedisSpider、指定redis_key就行了。

缺點:scrapy-redis調度的任務是Request對象,里面信息量比較大(不僅包含url,還有callback函數、headers等信息),導致的結果就是會降低爬蟲速度、而且會占用Redis大量的存儲空間。當然我們可以重寫方法實現調度url。

 

 

參考原文:https://segmentfault.com/a/1190000014333162?utm_source=channel-hottest


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM