• 路飞学城—Python爬虫实战密训班 第三章


     

    路飞学城—Python爬虫实战密训班 第三章

    一、scrapy-redis插件实现简单分布式爬虫

    scrapy-redis插件用于将scrapy和redis结合实现简单分布式爬虫:
        - 定义调度器
        - 定义去重规则: 本质利用redis 集合元素不重复(被调度器使用) # 看源码request_seen函数
     
    安装: pip3 install scrapy-redis
    

      

    1. redis配置文件settings.py

    #from scrapy_redis import defaults                         # 查看默认配置
    REDIS_HOST = '192.168.11.81'                            # 主机名
    REDIS_PORT = 6379                                       # 端口
    # REDIS_URL = 'redis://user:pass@hostname:9001'           # 连接URL(优先于以上配置)
    # REDIS_PARAMS  = {}                                      # Redis连接参数             默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
    # REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'     # 指定连接Redis的Python模块  默认:redis.StrictRedis
    REDIS_ENCODING = "utf-8"                                # redis编码类型             默认:'utf-8'
    连接Redis
    from scrapy_redis.scheduler import Scheduler
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"        # 使用该调度器,scrapy-redis原生调度器被替换掉
    
    from scrapy_redis.queue import PriorityQueue
    from scrapy_redis import picklecompat
    SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'              # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
    SCHEDULER_QUEUE_KEY = '%(spider)s:requests'                              # 调度器中请求存放在redis中的key
    SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"                      # 对保存到redis中的数据进行序列化,默认使用pickle
    SCHEDULER_PERSIST = True                                                  # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
    SCHEDULER_FLUSH_ON_START = False                                          # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空。本地测试可以为true,实际工作中False
    SCHEDULER_IDLE_BEFORE_CLOSE = 10                                          # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
    SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter'                      # 去重规则,在redis中保存时对应的key
    SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'      # 去重规则对应处理的类
    设置调度器
    from scrapy_redis.pipelines import RedisPipeline
    
    ITEM_PIPELINES = {
       'scrapy_redis.pipelines.RedisPipeline': 300,
    }
    
    REDIS_ITEMS_KEY = '%(spider)s:items'
    REDIS_ITEMS_SERIALIZER = 'json.dumps'    # 指定下序列化
    数据持久化

    2. 当url太长时,数据库保存占空间,创建唯一标识符

    from scrapy.utils import request
    from scrapy.http import Request
    
    
    obj1 = Request(url='http://www.baidu.com?id=1&name=3')
    obj2 = Request(url='http://www.baidu.com?name=3&id=1')        # 当传参一致时,创建的标识符也一样
    
    v = request.request_fingerprint(obj1)
    print(v)
    v = request.request_fingerprint(obj2)
    print(v)
    test.py

    3. 起始URL相关

    from scrapy_redis.pipelines import RedisSpider
    class ChoutiSpider(scrapy.RedisSpider):
        name = "chouti"
        allowed_domains = ["chouti.com"]
    
        def parse(self, response):
            for i in range(0,10):
                yield
    chouti.py:不用写起始url,但是这个爬虫不会终止, 不用redis的话 爬虫下载完url后会终止。

    4. 小结

    1. memcached
         
    2. Django缓存
     
    3. redis
        - 连接
            - StrictRedis()
            - Redis(StrictRedis)    # 继承StrictRedis
            - 连接池
             
        - 基本操作
            ..
             
        - 事务
     
        - 发布和订阅
         
    4. scrapy-redis流程
        4.1 引擎,获取起始Request对象, 添加(pickle)到调度器
            - scrapy内部调度器
            - scrapy-redis调度器三个选择:先进先出列表,后进先出列表,有序集合
     
        4.2 调度器通知下载器可以开始下载,去调度器中获取request对象(通过pickle存储request对象),下载器进行下载           
         
        4.3 爬虫parse方法,yield返回对象item或request
            - item              交给pipeline处理
            - request           交给调度去处理,调用DUPEFILTER_CLASS去检查是否已经访问过,来决定request重新放置调度器或者丢弃
     
     
         
     
        scrapy-redis扩种:
            - 中间件
            - 基于信号的扩展
    

    三、scrapy-redis示例

    # DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    #
    #
    # from scrapy_redis.scheduler import Scheduler
    # from scrapy_redis.queue import PriorityQueue
    # SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    # SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'          # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
    # SCHEDULER_QUEUE_KEY = '%(spider)s:requests'                         # 调度器中请求存放在redis中的key
    # SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"                  # 对保存到redis中的数据进行序列化,默认使用pickle
    # SCHEDULER_PERSIST = True                                            # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
    # SCHEDULER_FLUSH_ON_START = False                                    # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空
    # SCHEDULER_IDLE_BEFORE_CLOSE = 10                                    # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
    # SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter'                  # 去重规则,在redis中保存时对应的key
    # SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'# 去重规则对应处理的类
    #
    #
    #
    # REDIS_HOST = '10.211.55.13'                           # 主机名
    # REDIS_PORT = 6379                                     # 端口
    # # REDIS_URL = 'redis://user:pass@hostname:9001'       # 连接URL(优先于以上配置)
    # # REDIS_PARAMS  = {}                                  # Redis连接参数             默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
    # # REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块  默认:redis.StrictRedis
    # REDIS_ENCODING = "utf-8"                              # redis编码类型             默认:'utf-8'
    配置文件
    import scrapy
    
    
    class ChoutiSpider(scrapy.Spider):
        name = "chouti"
        allowed_domains = ["chouti.com"]
        start_urls = (
            'http://www.chouti.com/',
        )
    
        def parse(self, response):
            for i in range(0,10):
                yield
    爬虫文件

    四、总结

      WuSir为了给我们介绍分布式爬虫,他首先用了个典型的例子举例。问题是:在不考虑开进程和线程(比如这些都已经做好了)如何提高爬虫的性能?说到这可能大家心里都已经有答案了,没错,我最帅!

     
      好了,回到正题;既然进程和线程都不需要我们考虑的情况下,那么我们的一般选择就应该是多加些机器一起爬,但是随之而来的又有一个问题、单纯的增加机器,不让它们相互协调的工作,这会造成会重复的做相同的无用功,也就是会爬到相同的URL。要是不让它们协调在一起,这个方案也就没意义了。
     
      既然问题已经抛出,那么我们就可以引入答案了,也就是如题所说的:scrapy-redis、使用该模块可以帮助我们实现分布式爬虫。我们需要做的则是对他进行相应的操作和配置或者扩展,来进行使用它即可达到我们的目的。

      

  • 相关阅读:
    字节跳动--今日头条iOS客户端启动速度优化
    RSA加密
    几种浏览器
    Linux定时任务crontab无法执行
    Python报错ImportError: No Module Named Typing的解决
    微信小程序:A、B两个小程序相互跳转,出现点击A小程序底部导航栏菜单,第一次点击无法跳转B小程序,需要点击第二次才会触发跳转到B小程序
    c# core 生成随机图文验证码
    携程Apollo统一配置管理中心
    WPF程序中嵌入winForm窗体
    sqlserver 转 postgresql
  • 原文地址:https://www.cnblogs.com/sunday294/p/9301584.html
Copyright © 2020-2023  润新知