1. 程式人生 > >scrapy和scrapy-redis的區別

scrapy和scrapy-redis的區別

scrapy是一個python爬蟲框架,爬取的效率極高,具有高度的定製性,但是不支援分散式。而scrapy-redis是一套基於redis庫,執行在scrapy框架之上的元件,可以讓scapy支援分散式策略

Slaver端共享Master端redis資料庫裡的item 佇列、請求佇列和請求指紋集合。

選擇redis資料庫的原因:

  redis支援主從同步,而且資料都是快取在記憶體中的,所以基於redis的分散式爬蟲,對請求和資料的高頻率讀取效率都非常高

    scrapy-redis和scrapy的關係就像電腦和固態硬碟一樣,是電腦中的一個外掛,能讓電腦更快的執行

    scrapy是一個爬蟲框架,scrapy-redis則是這個框架上可以選擇的外掛,它可以讓爬蟲跑得更

 

 

解釋說明:

  1. 從優先順序佇列中獲取requests物件,交給engine
  2. engine將requests對此昂交給下載器下載,期間會通過downlomiddleware的process_request方法
  3. 下載器完成下載,獲得response物件,將該物件交給engine,期間會經過downloadmiddleware的process_response()方法
  4. engine將獲得的response物件交給spider進行解析,期間會經過spidermiddleware的process_spider_input()方法
  5. spider解析下載器下載下來的response,返回item或links(url)
  6. item或者link經過spidermiddleware的process_spider_out()方法,交給engine
  7. engine將item交給item pipeline,將links交給排程器
  8. 在排程器中,先將requests物件利用scrapy內建的指紋函式生成一個指紋
  9. 如果requests物件中的don't filter引數設定為False,並且該requests物件的指紋不在資訊指紋的佇列中,那麼就把該requests物件放到優先順序佇列中

 

中介軟體:

  spider與engine之間(爬蟲中介軟體)

    介於scrapy引擎和爬蟲之間的框架,主要工作就是處理爬蟲的響應輸入和請求的輸出

  download與engine之間(下載器中介軟體)

    介於scrapy引擎和下載器之間的框架,主要是處理scrapy引擎與下載器之間的請求和響應

 

scrapy框架中的middleware.py

  1. Scrapy Middleware有以下幾個函式被管理
    1. process_spider_input:接收一個response物件並處理
    2. process_spider_exception:spider出現異常時被呼叫
    3. process_spider_output:當spider處理response返回result時,就會呼叫該方法
    4. process_spider_requests:當spider發出請求時,被呼叫
  2. Download Middleware有以下幾個函式被管理
    1. process_requests:requests通過下載中介軟體的時候,該方法被呼叫,這裡可以通過設定代理,設定request.meta['proxy']就OK了
    2. process_response:下載結果經過中介軟體的時候會被這個方法解惑來進行處理
    3. process_exception:下載過程中出現異常的時候會被呼叫

 

Scrapy的優缺點:

  1. 優點
    1. scrapy是非同步處理的,寫middleware,方便寫一些統一的過濾器
  2. 缺點
    1. 基於python的爬蟲框架,擴充套件性比較差,基於twisted框架,執行中的exception是不會幹掉reactor,並且非同步框架出錯後是不會停掉其他任務的,資料出錯後難以察覺

 

Scrapy-Redis提供了四種元件(四種元件也就意味著這四個模組都需要做出相應的改動):

  1. Scheduler
    1. scrapy改變了python原本的collection.deque(雙向佇列)形成了自己的Scrapy queue,但是Scrapy多個spider不能共享爬取佇列Scrapy queue,也就是Scrapy本身不支援爬蟲的分散式,scrapy-redis的解決是把這個Scrapy queue換成了redis資料庫(也是指redis佇列),從同一個redis-server存放要爬取的request,就可以讓多個爬蟲去同一個資料庫裡讀取了
    2. scrapy中跟待爬佇列直接相關的就是排程器Scheduler,它負責對新的request進行入列操作(加入到Scrapy queue),取出下一個要爬的request(從Scrapy queue中取出來)等操作。它把待爬佇列按照優先順序建立一個字典結構,然後根據request中的優先順序,再來決定該入哪個佇列,出列時就按照優先順序較小的優先出列,為了管理這個比較高階的佇列字典,Scheduler需要提供一系列的方法,但是原來的Scheduler已經無法使用,所以使用Scrapy-redis的Scheduler元件
  2. Duplication Filter
    1. scrapy中用集合實現這個request的去重功能,scrapy中把已經發送的request指紋放入到一個集合中,把下一個request的指紋拿到集合中進行比較,如果該指紋已經存在集合中了,說了這個request傳送過了,如果沒有的話就繼續這個操作
    2. 在scrapy-redis中去重是由Duplication Filter元件來實現的,它通過redis的set不重複的特性,巧妙的實現了Duplicating Filter去重。scrapy-redis排程器從引擎接受request,將request的指紋存入redis的set檢查是否產生了重複,並將不重複的request push寫入redis的request queue
    3. 引擎請求request時,排程器從redis的request queue佇列里根據優先順序進行pop出一個request返回給engine,engine將這個request傳送給spider進行處理
  3. Item Pipeline
    1. 引擎(spider返回的)將爬取到的item給item pipeline,scrapy-redis的item pipeline將爬取到的item存入到redis的items queue
    2. 修改過的item pipeline可以很方便的根據key從items queue提取item,從而實現items processes叢集
  4. Base Spider
    1. 不在使用scrapy原有的Spider類,重寫RedisSpider繼承了Spider和RedisMixin這兩個類,RedisMixin是用來從redis中讀取url的類
    2. 當我們生成一個Spider繼承RedisSpider的時候,呼叫setup_redis函式,這個函式會去連線redis資料庫,然後就設定signals(訊號):一個是當spider空閒時候的signal,會呼叫spider_idle函式,這個函式呼叫scheduler_next_request函式,保證spider是一直活著的狀態,並且丟擲DontCloseSpider異常,還有一個就是當抓到一個item的signal,會呼叫item_scrapy函式,這個函式會呼叫scheduler_next_request函式,獲取下一個request。

 

Scrapy-Redis分散式策略:

    首先要說一下Master端和Slaver端

    1. Master
      1. 核心伺服器,搭建Redis資料庫,不負責爬取,只負責url指紋判斷是否重複、request的分配、以及資料的儲存
    2. Slaver
      1. 爬蟲程式執行端,負責執行爬蟲程式,執行過程中提交新的request給Master

    

    首先Slaver端從Master端拿任務(request, url)進行資料爬取,Slaver抓取資料的同時,產生新的request就提交給Master進行處理

    Master端只有一個Redis資料庫,負責將未處理的request去重和任務分配,將處理後的request加入待爬取的佇列,並且儲存爬取的資料

 

將scrapy變成scrapy-redis的過程(前提是已經安裝好了scrapy-redis)

  1. 修改settings.py配置檔案,最簡單的方式就是使用redis來替換當前電腦的記憶體,並且同時配置好redis資料庫相關的內容
    # 這個是需要手動加上的,通過scrapy-redis自帶的pipeline將item存入redis中
    ITEM_PIPELINES = {'scrapy_redis.pipelines.RedisPipeline': 400
    }
    # 啟動redis自帶的去重
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    # 啟用排程器
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    # 是否在關閉spider的時候儲存記錄
    SCHEDULER_PERSIST = True
    # 使用優先順序排程請求佇列(預設使用)
    SCHEDULER_QUEUE_CLASS = 
     'scrapy_redis.queue.SpiderPriorityQueue'
    # 指定redis的地址和埠,有密碼的需要加上密碼
    REDIS_HOST = '127.0.0.1'
    REDIS_PORT = '6379'
    # 如果你的redis設了密碼就需要加上密碼, REDIS_PARAMS = { 'password': '123456', }

     

     

&n