• python分布式爬虫框架 --- scrapy-redis


    scrapy-redis模块

    scrapy-redis是为了实现scrapy的分布式爬取而提供了一个python库,通过更换scrapy的内置组件,将爬取请求队列和item数据放入第三方的redis数据库中,由此可以有多个scrapy进程从redis中读取request数据和写入items数据,实现分布式处理。

    redis主要工作:

    • 储存request请求,形成一个队列供不同的多个scrapy进行消费。scrapy-redis提供了三种队列,可自由配置。
      • PriorityQueue(优先队列:默认):通过redis的有序集合实现,同时集合可以自动对request去重
      • FifoQueue和LifoQueue:通过List实现
    • 储存item数据
    • 对request进行去重,需要使用一个集合的数据结构来实现快速的去重。

    安装scrapy-redis

    pip install scrapy-redis即可安装,官方要求python和redis版本如下:

    • Python 2.7, 3.4 or 3.5
    • Redis >= 2.8
    • Scrapy >= 1.1
    • redis-py >= 2.10

    配置scrapy-redis

    scrapy-redis是在原scrapy的基础上,通过替换部分scrapy组件来实现,这些组件包括。

    • Scheduler:使用redis作为request的调度队列,需要更换schedule类,配置文件中配置即可
    • Duplication Filter:通过redis的set对request进行去重,去重的指纹采用method+url+body+header的信息,通过hash函数生成hash值存入redis的一个set中,使用时在配置文件中直接配置即可
    • Item Pipeline:使用一个pipeline将爬取的数据储存到redis服务中,配置文件中添加该类即可
    • Base Spiders:spider对象是一个爬虫的核心对象,该类的定义由我们自己实现,在原来scarapy框架中通过继承内置Spider类来获得了公用的功能。这里我们需要使用scrapy-redis提供的RedisSpider类作为父类,继承与redis进行连接通信的方法,而不用我们手动连接redis。

    更换上述的组件的方式通过配置文件即可完成,只有spider类的定义需要我们更改继承的父类即可。

    配置文件

    作者给出可添加的配置文件的全部内容,需要时进行添加配置即可。githu地址https://github.com/rmax/scrapy-redis

    # Enables scheduling storing requests queue in redis.
    配置后使用redis中队列实现了request的调度。
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    
    # 过滤重复request方式,避免重复爬取
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    
    # 默认使用pickle进行序列化,可以指定为“json”或 “msgpack”
    #SCHEDULER_SERIALIZER = "json"  # "msgpack"   json和msgpack均可调用dump和loads方法
    SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"
    
    # 不会清空request队列,阻塞等待downloader获取request爬取
    #SCHEDULER_PERSIST = True
    
    # Schedule requests 默认使用PriorityQueue (优先队列)
    SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
    # 其他可选的有
    #SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
    #SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'
    
    # Max idle(闲置) time 分布式情况下最大的闲置时间,超过该时间该spider没有获取数据则可能已经关闭.
    # queue class 是 SpiderQueue or SpiderStack 时才生效
    # 这可能会让你的爬虫刚开始启动时阻塞的,因为这个queue是空的
    #SCHEDULER_IDLE_BEFORE_CLOSE = 10
    
    
    # Store scraped item in redis for post-processing.
    # 处理item的类,该类会将item保存到redis的中,并使用指定的序列化方式,和REDIS_ITEMS_KEY指定的key储存
    ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline': 300
    }
    
    # item信息被序列化后储存在该key中,默认key为
    REDIS_ITEMS_KEY = '%(spider)s:items'
    
    # 将item对象进行序列化的方式,默认为 ScrapyJSONEncoder. 可以指定其他序列化方式,指定一个序列化函数即可,例如下面json.dump
    #REDIS_ITEMS_SERIALIZER = 'json.dumps'
    
    # Specify the host and port to use when connecting to Redis (optional).
    #REDIS_HOST = 'localhost'
    #REDIS_PORT = 6379
    # 设置后优先选择url的方式连接
    #REDIS_URL = 'redis://user:pass@hostname:9001'
    
    # Custom redis client parameters (i.e.: socket timeout, etc.)
    #REDIS_PARAMS  = {}
    # Use custom redis client class.
    #REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'
    
    # 多个start_url时是否储存为一个set,方便去重
    #REDIS_START_URLS_AS_SET = False
    
    # starturl储存在redis中的key的名字
    #REDIS_START_URLS_KEY = '%(name)s:start_urls'
    
    # Use other encoding than utf-8 for redis.
    #REDIS_ENCODING = 'latin1'

    以上是全部的配置文件的内容,通常不用进行全部的配置,添加下面的配置即可

    # 更换scheduler组件
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    # SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'   # 如果不指定使用优先队列
    
    # 指定对request去重所使用的类,该类继承自scrapy中的饿BaseDupeFilter,重写了部分方法
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    
    # 更改原配置文件中的ITEM_PIPELINES
    ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline': 300,  # 该pipeline是item数据写入redis,也可以指定其他pipeline
    }
    
    # 在redis中保存item数据的key的名字
    REDIS_ITEMS_KEY = '%(spider)s:items'
    REDIS_HOST = '192.168.236.100'
    REDIS_PORT = 6379
    
    # start_url储存在redis中的key的名字, 该值在会绑定在spider对象的redis_key属性上
    REDIS_START_URLS_KEY = '%(name)s:start_urls'

    spider

    spider需要从scrapy-redis模块中继承spider类,scrapy中有两个spider类,分别为Spider和CrawlSpider类,scrapy-redis通过Mixin的方式,将RedisMixin类混入原来的两个spider类中,得到了RedisSpider和RedisCrawlSpider,使用时将原来的spider类对应更换为新的RedisSpider或RedisCrawlSpider类即可

    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import Rule  # CrawlSpider
    from scrapy.http.response.html import HtmlResponse
    from scrapy_redis.spiders import RedisCrawlSpider
    
    
    class ReviewSpider(RedisCrawlSpider):  # 使用RedisCrawlSpider替换原CrawlSpider类
        name = 'name'
        allowed_domains = ['domain.com']
        # 如果指定了start_urls,会将该start_urls存如redis对应的指定的key中
        # 如果没有指定,scrapy将阻塞等待redis的start_urls对应的key中被添加url来开始爬取
        # start_urls = []
        redis_key = "reviews:start_url"   # start_url对应redis中的key,没有指定使用配置文件中的REDIS_START_URLS_KEY = '%(name)s:start_urls'配置的值作为key
    
        rules = (
            Rule(LinkExtractor(allow=r'Item'), callback='parse_item', follow=True),
        )
    
        def parse_item(self, response: HtmlResponse):
            pass
            # return items

    运行scrapy

    更改以上配置后,运行该scrapy爬虫,由于start_url中没有起始的url,程序将会阻塞等待提供起始url,scrapy时从redis中获取url,且key为上述spider中定义的redis_key属性的内容,即"reviews:start_url",所以只需要手动向该key写入一个start_url数据即可开始爬取。该key的类型默认为一个List,(除非配置文件中有一个选项指定该key的为一个set)。

    进入redis客户端,执行lpush reviews:start_url <start_url>添加一个初始url即可开始爬取。

    运行后查看redis中的数据,增加了三个key信息。

    • review:dupefilter:类型为set,存放已爬取request指纹信息,保存的是每个request经过hash函数计算后的结果
    • review:items:类型为list, 存放经过序列化后的item数据,默认使用json.dumps的序列化方式。
    • review;start_url:类型为list,起始的url数据。

     

  • 相关阅读:
    java如何得到GET和POST请求URL和参数列表
    Java中,当表单含有文件上传时,提交数据的如何读取
    图片文件,图片文件流和BASE64加密字符串之间的转换,以及图片的BASE64加密字符串再jsp上如何显示
    Multipart/form-data POST文件上传详解(转)
    如何控制微信分享网页时,展示的标题,描述和图片
    微信的分享功能(针对web手机站页面进行的分享功能)
    关于linux下内存使用的一些疑惑[转载]
    【转】《高级前端3.6》JavaScript多线程——Concurrent.Thread.js, WebWork
    【转】javascript中的LHS与RHS
    [转] linux系统中如何进入退出vim编辑器,方法及区别
  • 原文地址:https://www.cnblogs.com/k5210202/p/13079652.html
Copyright © 2020-2023  润新知