介绍

原来 scrapy 的 Scheduler 维护的是本机的任务队列(存放 Request 对象及其回调函数等信息)+ 本机的去重队列(存放访问过的url地址)

所以实现分布式爬取的关键就是,找一台专门的主机上运行一个共享的队列比如 Redis,
然后重写 Scrapy 的 Scheduler,让新的 Scheduler 到共享队列存取 Request,并且去除重复的 Request 请求,所以总结下来,实现分布式的关键就是三点:

#1、共享队列
#2、重写Scheduler,让其无论是去重还是任务都去访问共享队列
#3、为Scheduler定制去重规则(利用redis的集合类型)

安装

pip install scrapy-redis

#源码:
D:\python3.6\Lib\site-packages\scrapy_redis

scrapy-redis 组件

只使用scrapy-redis的去重功能

在 settings.py 中配置链接 Redis

REDIS_HOST = 'localhost'                            # 主机名
REDIS_PORT = 6379                                   # 端口
REDIS_URL = 'redis://user:pass@hostname:9001'       # 连接URL(优先于以上配置)
REDIS_PARAMS  = {'password':'redis123'}             # Redis连接参数
REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块
REDIS_ENCODING = "utf-8"                            # redis编码类型 

让 scrapy 使用共享的去重队列

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

from scrapy.dupefilters import RFPDupeFilter
from scrapy.core.scheduler import Scheduler

将request请求转成一串字符后再存入集合

from scrapy.http import Request
from scrapy.utils.request import request_fingerprint

req = Request(url='http://www.baidu.com')
result=request_fingerprint(req)
print(result) #75d6587d87b3f4f3aa574b33dbd69ceeb9eafe7b

注意:
UR L参数位置不同时,计算结果一致;
默认请求头不在计算范围,include_headers 可以设置指定请求头

req = Request(url='http://www.baidu.com?name=8&id=1',callback=lambda x:print(x),cookies={'k1':'vvvvv'})
result1 = request.request_fingerprint(req,include_headers=['cookies',])
print(result)
 
req = Request(url='http://www.baidu.com?id=1&name=8',callback=lambda x:print(x),cookies={'k1':666})
result2 = request.request_fingerprint(req,include_headers=['cookies',])
print(result1 == result2) #True

使用 scrapy-redis 的去重 + 调度实现分布式爬取

settings.py 配置

# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"   

# 调度器将不重复的任务用 pickle 序列化后放入共享任务队列,默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)               


步骤

1 原来的爬虫继承

from scrapy_redis.spiders import RedisSpider

class ChoutiSpider(RedisSpider):
    name = 'chouti'  # 爬虫名字
    redis_key = 'myspider:start_urls'

2 在 settings 中配置

  SCHEDULER = "scrapy_redis.scheduler.Scheduler"
  DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
  ITEM_PIPELINES = {
     'scrapy_redis.pipelines.RedisPipeline': 300
  }

3 多台机器上启动 scrapy

4 向 redis 中发送起始 url

lpush myspider:start_urls https://www.cnblogs.com
 posted on 2020-04-12 18:29  Rannie`  阅读(217)  评论(0编辑  收藏  举报
去除动画
找回动画