天天看點

scrapy分布式爬蟲

scrapy_redis

scrapy是一個通用的爬蟲架構,但是不支援分布式,scrapy_redis是為了更友善的實作scrapy分布式爬取,而提供了一些以redis為基礎的元件(僅有元件)。

scrapy_redis工作原理:

  1. 排程器将不再負責Url的排程,而是将url上傳給scrapy_redis元件,由元件負責組織、去重
  2. redis元件會通過指紋(key)來進行去重操作,并且把請求對象分發給不同的用戶端
  3. 用戶端拿到請求對象後,再交給引擎–下載下傳器
  4. pipeline不再負責本地化操作,而是把資料交給redis元件來負責寫入redis資料庫,達到資源共享、自動合并的目的

scrapy_redis組成:

Scheduler 排程器,scrapy本身不支援爬蟲分布,scrapy_redis的解決是把這個scrapy queue換成redis資料庫(也是指redis隊列),從同一個redis-server存放要爬取的request,便能讓多個spider去同一個資料庫裡讀取。

Duplication Filter 指紋過濾器,scrapy用集合實作這個request去重功能,scrapy中把已經發送的request指紋放到一個集合中,把下一個request的指紋放到集合中比對,如果該指紋存在于集合中,說明這個request發送過了,如果沒有則繼續操作。

Item Pipeline 管道,引擎将(spider傳回的)爬取到的item給Item Pipeline,scrapy_redis的Item Pipeline将爬取到的item存入redis的items pipeline。

Base Spider

分布式爬蟲例子(爬取讀書網的圖書名稱和封面圖檔連結,正常設定或者不需要修改的部分代碼就沒貼了):

# settings.py檔案增加配置

# 去重類的引入
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# redis排程器的引用
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# redis是否本地化的開關
SCHEDULER_PERSIST = True

# 分布式爬蟲需要配置要通路的redis的主機
REDIS_HOST = '10.11.56.63'  # 主機ip
REDIS_PORT = 

ITEM_PIPELINES = {
   'dushuProject.pipelines.DushuprojectPipeline': ,

    # 導入依賴
   'scrapy_redis.pipelines.RedisPipeline':,
}

# 延時1s(反爬蟲)
DOWMLOAD_DELAY = 
           
# items.py檔案,即要爬取的資料字段

import scrapy
class DushuprojectItem(scrapy.Item):
    title = scrapy.Field()
    img_url = scrapy()
           
# pipelines.py檔案,未作修改
class DushuprojectPipeline(object):
    def process_item(self, item, spider):
        return item
           
# read2.py檔案(爬蟲檔案,讀書網)

# -*- coding: utf-8 -*-
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import Rule
from scrapy_redis.spiders import RedisCrawlSpider  # 導入RedisCrawlSpider

class Read2Spider(RedisCrawlSpider):  # 繼承的父類修改一下
    name = 'read2'  # 爬蟲名字
    # start_urls = ['https://www.dushu.com/book/1081.html']  # 初始url

    # 鍵名稱的一般規則  爬蟲名字:start_urls
    redis_key = 'read2:start_urls'  # 由主機提供

    # 指定了頁面内,連結的提取規則,會被父類自動調用
    rules = (
        Rule(LinkExtractor(allow=r'/book/1081_\d+.html'), callback='parse_item', follow=False),
    )

    # 頁面資料解析函數
    # 可以自定義,隻要保證callback的參數與這個函數名一緻即可
    def parse_item(self, response):
        # 每頁的圖書清單
        book_list = response.xpath('//div[@class="bookslist"]//li')

        for each in book_list:
            i = {}
            i['title'] = each.xpath('.//h3//@title').extract_first()
            i['img_url'] = each.xpath('.//img/@src').extract_first()

            print(i)
            yield i
           
# 執行分布式爬蟲的步驟:

# 1. 本地運作以下指令
scrapy runspider read2.py

# 2. 主機端開啟redis服務
# 另開視窗
redis-cli
lpush redis_key start_url  # 推送start_url
# 例如 lpush read2:star_url "https://www.dushu.com/book/1081.html"
           

遠端連接配接redis:

redis-cli -h ip -p 6379 -a password

繼續閱讀