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', }

     

     

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章