zoukankan      html  css  js  c++  java
  • 分布式爬虫

    分布式爬虫

    • 实现方式:scrapy+redis(scrapy结合这scrapy-redis组件)
    • 原生的scrapy框架是无法实现分布式
      • 需要搭建一个分布式的机群,让后让机群中的每一台电脑执行同一组程序,让其对同一组资源 进行联合且分布的数据爬取。
      • 为什么原生的scrapy框架无法实现分布式
        • 1.调度器无法被分布式机群共享
        • 2.管道无法被分布式机群共享
      • scrapy-redis组件的作用:
        • 可以给原生的scrapy框架提供共享的管道和调度器
        • pip install scrapy-redis

    步骤

    1.修改爬虫文件

    -1.1导包from scrapy_redis.spiders import RedisCrawlSpider

    -1.2将源文件中的父类修改成RedisCrawlSpider

    -1.3将start_url替换成redis_keys的属性,属性值为任意字符

    - redis_key = 'xxx':表示的是可以被共享的调度器队列的名称,最终是需要将起始的url手动放置到		redis_key表示的队列中,所以start_url都注释了,后续需要在redis中输入网址即可
    
    

    -1.4将数据解析完整即可

    2.对settings.py进行配置

    • 指定调度器

      • 增加一个去重容器类的配置,作用使用Redis的set集合来存储请求的指纹数据,从而实现请求去重的持久化

      • 直接将以下三个配置放到settings中(复制粘贴即可)

         # 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
                    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
                    # 使用scrapy-redis组件自己的调度器
                    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
                    # 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
                    SCHEDULER_PERSIST = True
        
    • 指定管道(复制粘贴到settings中,不可以自定义,封装好的)

      • ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 400 }
        • 特点:该种管道只可以将item写入redis,(这里补充一下redis,他不能存储大文件,他是内存数据库,就算持久化他也是断电之前将数据存储在本地,然后开机就将数据加载到内存中)
    • 指定redis

      • REDIS_HOST = 'redis服务的ip地址' (由于测试使用127.0.0.1的,将来使用真实的redis所在的ip地址)

      • REDIS_PORT = 6379

      • # REDIS_ENCODING = ‘utf-8’
        # REDIS_PARAMS = {‘password’:’123456’}
        将来redis如果有账号密码加上这个配置
        

      3.配置redis的配置文件(redis.window.conf)

      • 解除默认绑定 (意思就是允许其他ip地址的客户端远程访问)
        • 56行:#bind 127.0.0.1

    • 关闭保护模式() (保护模式就是别的客户端只能读数据,不能写数据。关闭就远程客户端可以写数据了)

      -75行:protected-mode no (将yes改成no)

    4.启动redis服务和客户端

    5.执行scrapy工程(不要在配置文件中加入LOG_LEVEL)

    启动之后你会发现项目在监听,在等,等传入起始的url加入

    6.向redis_key表示的队列中添加起始url

    当初咱们在spider源文件中写了redis_key了

    需要在redis的客户端执行如下指令:(调度器队列是存在于redis中)

    lpush sunQueue http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1
    

    lpush 将起始的url就是你想爬取的url扔进去,没有此key会自动创建,不用担心,sunQueue千万别忘了是你的队列名字,你起的什么 就些什么

    !!!当你输入完这句话后,你就会看到监听的终端会开始下载了

    好的体验就是将settings中的线程数改小一点,假如你是32线程,当其他人的电脑配置特别低的话,就是调度器发布任务,抢不到资源,他就不干活了,所以你最好设置低一点的线程,当你的线程都在执行,别人电脑配置在低也能抢到资源,当然这个只是为了看效果,但是实战的时候不要将线程数改的特别低!!!!

    spider源文件

    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    from scrapy_redis.spiders import RedisCrawlSpider
    from fbs_project.items import FbsProjectItem
    class TestSpider(RedisCrawlSpider):
        name = 'test'
        # allowed_domains = ['www.xxxx.com']
        # start_urls = ['http://www.xxxx.com/']
        redis_key='sunQueue' #可以被共享的调度器队列的名称
        #稍后我们是需要将一个起始的url手动的添加到redis_key表示的队列中
    
        rules = (
            Rule(LinkExtractor(allow=r'id=1&page=d+'), callback='parse_item', follow=True),
        )
    
        def parse_item(self, response):
            # 将全站的标题获取
            li_list = response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
            for li in li_list:
                title = li.xpath('./span[3]/a/text()').extract_first()
                item = FbsProjectItem()
                item['title'] = title
                yield item
    
    
  • 相关阅读:
    批处理命令之实现修改环境变量的值
    【hihocoder 1304】搜索一·24点
    【hihocoder 1297】数论四·扩展欧几里德
    【hihocoder 1298】 数论五·欧拉函数
    【hihocoder 1303】模线性方程组
    C语言如何动态分配二维数组
    Istream中的函数
    string 与 char * 转换
    boost 系列 1:boost 直接使用
    glog功能介绍 一分钟 51CTO技术博客
  • 原文地址:https://www.cnblogs.com/zzsy/p/12694915.html
Copyright © 2011-2022 走看看