scrapy-redis是一个基于redis的scrapy组件,通过它可以快速实现简单分布式爬虫程序,该组件本质上提供了三大功能:
- scheduler - 调度器
-
- dupefilter - URL去重规则(被调度器使用)
- pipeline - 数据持久化
scrapy-redis组件
1. URL去重
a
a. 利用scrapy-redis做去重规则:
# ############ 连接redis 信息 #################
REDIS_HOST = \'127.0.0.1\' # 主机名
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"
# 自定义去重规则
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
可以自定义一个去重的类
dup.py
from scrapy_redis.dupefilter import RFPDupeFilter
class MyRFPDupeFilter(RFPDupeFilter):
#继承那个类然后写一些自己定义的方法
pass
# 在setting中选择自己自定义去重规则
DUPEFILTER_CLASS = "wenwen.dup.MyRFPDupeFilter"
配置:
# ############ 连接redis 信息 #################
REDIS_HOST = \'127.0.0.1\' # 主机名
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"
# 自定义去重规则 如果是自定义去重规则的话详见上文
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# ############ 连接redis 信息 #################
REDIS_HOST = \'127.0.0.1\' # 主机名
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"
# 有引擎来执行:自定义调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_QUEUE_CLASS = \'scrapy_redis.queue.LifoQueue\' # 默认使用优先级队列(默认广度优先),其他: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 chouti:dupefilter
SCHEDULER_DUPEFILTER_CLASS = \'scrapy.dupefilter.RFPDupeFilter\' # 去重规则对应处理的类
#去重规则对应处理的类
DUPEFILTER_DEBUG = False
# ############ 连接redis 信息 #################
REDIS_HOST = \'127.0.0.1\' # 主机名
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"
# 有引擎来执行:自定义调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_QUEUE_CLASS = \'scrapy_redis.queue.LifoQueue\' # 默认使用优先级队列(默认广度优先),其他: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 chouti:dupefilter
SCHEDULER_DUPEFILTER_CLASS = \'scrapy_redis.dupefilter.RFPDupeFilter\' # 去重规则对应处理的类
DUPEFILTER_DEBUG = False
配置:
导入scrapy_redis的pipline
#使用scrapy_pipeline的
ITEM_PIPELINES = {
\'scrapy_redis.pipelines.RedisPipeline\': 300,
}
以上功能全部应用的配置:
# ############ 连接redis 信息 #################
REDIS_HOST = \'127.0.0.1\' # 主机名
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"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 有引擎来执行:自定义调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_QUEUE_CLASS = \'scrapy_redis.queue.LifoQueue\' # 默认使用优先级队列(默认广度优先),其他: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 chouti:dupefilter
SCHEDULER_DUPEFILTER_CLASS = \'scrapy_redis.dupefilter.RFPDupeFilter\' # 去重规则对应处理的类
DUPEFILTER_DEBUG = False
# 深度和优先级相关
DEPTH_PRIORITY = 1
配置:
REDIS_START_URLS_BATCH_SIZE = 1
# REDIS_START_URLS_AS_SET = True # 把起始url放到redis的集合
REDIS_START_URLS_AS_SET = False # 把起始url放到redis的列表
爬虫:
from scrapy_redis.spiders import RedisSpider
from scrapy.http import Request
from ..items import WenwenItem
class ChoutiSpider(RedisSpider):
name = \'chouti\'
allowed_domains = [\'chouti.com\']
def parse(self, response):
# 随着深度的增加、优先级一直在递减
print(response)
放置起始URL:
import redis
conn = redis.Redis(host=\'127.0.0.1\',port=6379)
# 起始url的Key: chouti:start_urls
conn.lpush("chouti:start_urls",\'https://dig.chouti.com/r/ask/hot/12\')