Python爬虫学习记录——17.分布式爬虫

分布式系统

当爬取内容过多,需要多机合作的时候,就需要用到分布式系统,这节博客讲解一下分布式爬虫的实现。

什么是分布式系统
分布式系统就是把一些计算机通过网络连接起来,然后协同工作
协同工作需要解决两个问题:

  • 任务分解
    把一个问题拆解成若干个独立任务,每个任务在一台节点上运行,实现多任务的并发执行

  • 节点通信
    节点之间互相通信,需要设计特定的通信协议来实现。协议可以采用RPC或Message Queue等方式

分布式爬虫系统

  • scrapy_redis

    • scrapy-redis是为了更方便地实现scrapy分布式爬取,而提供了一些以redis数据库为基础的组件
    • scrapy-redis提供了维持待爬取url的去重以及储存requests的指纹验证。原理是:redis维持一个共同的url队列,各个不同机器上的爬虫程序获取到的url都保存在redis的url队列,各个爬虫都从redis的url队列获取url,并把数据统一保存在同一个数据库里面
    • 本节博客主要讲授基于scrapy_redis的分布式爬虫
  • 消息队列

    • MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,消息发送后可以立即返回,由消息系统来确保消息的可靠传递
    • 它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订阅队列中的消息
    • 消息生产者只管把消息发布到 MQ 中而不用管谁来取,消息消费者只管从 MQ 中取消息而不管是谁发布的
  • RabbitMQ

    RabbitMQ是MQ产品的典型代表,是一款基于AMQP协议可复用的企业消息系统。业务上,可以实现服务提供者和消费者之间的数据解耦,提供高可用性的消息传输机制,在实际生产中应用相当广泛

  • scrapy_rabbitmq分布式

    Scrapy-rabbitmq-link 是可以让你从RabbitMQ 消息队列中取到URL并且分发给Scrapy spiders的组件

  • celery初步

    Celery 用消息通信,通常使用中间人(Broker)在客户端和程序间斡旋。这个过程从客户端向队列添加消息开始,之后中间人把消息派送给程序

scrapy_redis分布式

什么是Redis数据库
Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库

安装Redis数据库及scrapy_redi:
这里仅介绍Windows系统下的安装

  1. 下载Redis压缩包
    前往:https://github.com/MicrosoftArchive/redis/releases
    或者前往网盘链接:http://pan.baidu.com/s/1i5f9xSL 密码:t5bo
    下载Redis-x64-3.2.100.zip,并将其解压缩

  2. 安装Redis
    打开cmd,切换到解压的文件夹下执行命令

    redis-server –service-install redis.windows.conf –loglevel verbose
    
  3. 启动Redis服务
    在解压的文件夹下执行命令

    redis-server –service-start
    
  4. 安装scrapy_redis
    启动cmd,使用pip安装scrapy_redis

    pip install scrapy_redis
    

Scrapy_redis设置
在项目中进行如下的设置:

  • 更改去重对列必有项
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
  • 利用Redis去重:必有项
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
  • 序列化方案
SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"
  • 故障重跑
SCHEDULER_PERSIST = True
  • URL队列优先级
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
  • 把item储存进Redis管道
ITEM_PIPELINES = { 
'scrapy_redis.pipelines.RedisPipeline': 300 
}
  • 队列名字
REDIS_ITEMS_KEY = '%(spider)s:items'
  • 配置连接
REDIS_HOST = 'localhost'
REDIS_PORT = 6379 
#或者 
REDIS_URL = 'redis://user:pass@hostname:9001'
  • 实例化一个Redis对象
REDIS_PARAMS[‘redis_cls’] = 'myproject.RedisClient'
  • 设置set格式(不允许重复的元素)
REDIS_START_URLS_AS_SET = False
  • 键值对中键值命名规则
REDIS_START_URLS_KEY = '%(name)s:start_urls'
  • 编码方式
REDIS_ENCODING = 'latin1'

启动scrapy_redis

  1. 运行爬虫:

    scrapy crawl 爬虫名
    
  2. 启动:(注意:启动的时候应该先切换到redis安装目录下)

    • url选用的是list类型:
    redis-cli lpush myspider:start_urls http://google.com
    
    1. url选用的是set类型:
    redis-cli sadd myspider:start_urls http://google.com
    

实战

这次用的依然是上节课的city58的案例,只是修改了settings.py和city58_test.py两个文件。

  1. city58_test.py:实现翻页爬取

    # -*- coding: utf-8 -*-
    import scrapy
    from pyquery import PyQuery
    from ..items import City58Item
    
    from scrapy.http import Request
    from scrapy_redis.spiders import RedisSpider
    
    class City58TestSpider(RedisSpider):
        name = 'city58_test'
        allowed_domains = ['58.com']
        start_urls = ['http://bj.58.com/chuzu/']
    
        def parse(self, response):
            jpy = PyQuery(response.text)
            li_list = jpy('body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
            for it in li_list:
                a_tag = it('div.des > h2 > a')
                item = City58Item()
                item['name'] = a_tag.text()
                item['url'] = (a_tag.attr('href') if a_tag.attr('href') else '')
                item['price'] = it('div.listliright > div.money > b').text()
    
                yield item
    
            if not li_list:
                return
            pn = response.meta.get('pn',1)  #得到meta中pn的数值,如果没有,就默认为1
            pn += 1
            #response.meta['pn'] = p
    
            if pn > 5
                return
            #把相对路径转化为绝对路径,并request访问
            req = response.follow('/chuzu/pn{}/'.format(pn),   #拼接相对路径
                                  callback = self.parse,
                                  meta = {'pn':pn}   #使用meta参数进行传值
                                  )
            yield req
    
  2. settings.py

    SCHEDULER = "scrapy_redis.scheduler.Scheduler"   #必有项:更改去重对列
    
    # Ensure all spiders share same duplicates filter through redis.
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"   #必有项:利用Redis去重
    
    #SCHEDULER_PERSIST = True   #故障重跑
    REDIS_URL = 'redis://localhost:6379'   #配置连接
    #REDIS_START_URLS_AS_SET = False   #设置set格式(不允许重复的元素)
    
  3. 运行时要记得在队列中塞入start_urls

    redis-cli lpush city58_test:start_urls http://bj.58.com
    

redis desktop manager软件安装及使用

  1. Windows系统安装包下载
    前往网盘链接:http://pan.baidu.com/s/1gfpgQxt 密码:iz9u

  2. 根据提示进行安装
    只需要执行默认安装便可

  3. 打开软件,点击connect to redis server

  4. 输入数据库名字,以及host和端口
    数据库名字test,host为127.0.0.1(本机),默认端口为6379

  5. 打开数据库,就可以看到数据了

其他的分布式系统

本篇博客介绍了基于scrapy-redis的分布式系统,用于分布式爬虫URL队列的存储和去重队列的存储。当然,对于更大型的爬虫系统,或者对于非scrapy框架的爬虫,可以选择其它的方案替代scrapy和scrapy-redis,比如可以使用RabbitMQ消息队列代替Redis。以下的内容,提供了更多关于分布式爬虫的知识和方案

  • 消息队列
    MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订阅队列中的消息

    爬虫之消息队列
    在构建一个松耦合或是异步的系统时,消息队列是最常用的方法。在爬虫中使用消息队列有哪些好处呢?

    • 通过消息队列实现线程安全的去重
    • 多进程消费爬虫任务队列
    • 确保每一条任务都执行

    RabbitMQ消息队列
    RabbitMQ 是一种消息队列,用于程序间的通信
    形象地说 : MQ就像一个邮局,发送者将消息写入 MQ,MQ 负责把消息发送给接收者。RabbitMQ 可支持 Java, PHP, Python, Go, JavaScript, Ruby 等多种语言
    在这里插入图片描述
    注意:RabbitMQ的使用需要事先安装
    Scrapy-rabbitmq-link的安装和配置
    Scrapy-rabbitmq-link 是可以让你从RabbitMQ 消息队列中取到URL并且分发给Scrapy spiders的组件

    • 安装:
    pip install scrapy-rabbitmq-link
    
    • 配置:
    # Enable RabbitMQ scheduler
    SCHEDULER = "scrapy_rabbitmq_link.scheduler.SaaS"
    
    # Provide AMQP connection string
    RABBITMQ_CONNECTION_PARAMETERS = 'amqp://guest:guest@localhost:5672/'
    
    # Set response status codes to requeue messages on
    SCHEDULER_REQUEUE_ON_STATUS = [500]
    
    # Middleware acks RabbitMQ message on success
    DOWNLOADER_MIDDLEWARES = {
        'scrapy_rabbitmq_link.middleware.RabbitMQMiddleware': 999
    }
    
  • Celery - 分布式任务队列
    Celery 是一个简单、灵活且可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必需工具

    它是一个专注于实时处理的任务队列,同时也支持任务调度

    Celery 需要一个发送和接受消息的传输者。Celery 支持 RabbitMQ、Redis 甚至其他数据库系统作为其消息代理中间件,但也提供大量其他实验性方案的支持

    Celery 好处也很多,尤其在使用python构建的应用系统中,无缝衔接,使用相当方便

    celery的应用场景

    • 处理异步任务
    • 任务调度
    • 处理定时任务
    • 分布式调度
    • 安装Celery

    安装Celery

    pip install celery
    

    配置Celery

    from celery import Celery
    
    app = Celery('hello', broker='amqp://guest@localhost//')   #配置rabbitMQ
    
    @app.task  #装饰器
    def hello():
        return 'hello world'
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赈川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值