settings 配置文件:
# 使用scrapy-redis里的去重组件,不使用scrapy默认的去重方式
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis里的调度器组件,不使用默认的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 允许暂停,redis请求记录不丢失
SCHEDULER_PERSIST = True
# 默认的scrapy-redis请求队列形式(按优先级)
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# 队列形式,请求先进先出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
# 栈形式,请求先进后出
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
# 只是将数据放到redis数据库,不需要写pipelines文件
ITEM_PIPELINES = {
# 'Sina.pipelines.SinaPipeline': 300,
'scrapy_redis.pipelines.RedisPipeline': 400,
}
# LOG_LEVEL = 'DEBUG'
# Introduce an artifical delay to make use of parallelism. to speed up the
# crawl.
DOWNLOAD_DELAY = 1
# 指定数据库的主机IP
REDIS_HOST = "172.0.0.1"
# 指定数据库的端口号
REDIS_PORT = 6379
# redis 密码
REDIS_PARAMS = {
'password': **********,
}
spiders.py
不在使用scrapy原有的Spider类,重写的RedisSpider继承了Spider和RedisMixin这两个类,RedisMixin是用来从redis读取url的类。当我们生成一个Spider继承RedisSpider时,调用setup_redis函数,这个函数会去连接redis数据库
指定 redis_key = ' ' 替代start_urls 我们将在 redis 中push 起始url
这里我们要注意下,scrapy 起始请求调用 start_requests 方法 回调parse方法。如果我们重写了这个方法,而且改变了start_urls名字,会出现问题,我们大可不必这样, 可以在parse里面进行数据的处理或者新的url请求,然后回调其他函数parse_item或者其他,
from scrapy_redis.spiders import RedisSpider
class ToutiaoSpider(RedisSpider):
name = 'toutiao'
allowed_domains = ['toutiao.com']
redis_key = 'toutiao:start_urls'
# start_urls = ['http://open.toutiao.com/?']
def parse(self, response):
pass
xxxx
def parse_item():
pass
xxxx
启动爬虫 >>>>> 使用本地redis数据库
此时爬虫处于等待命令状态
我们在redis lpush起始url(可以写shell脚本去在启动爬虫的时候master端去push url )
127.0.0.1:6379> lpush toutiao:start_urls http://open.toutiao.com/?
lpush完成后 爬虫开工作
这里要注意的是在多个 爬虫运行时候,当一个爬虫url爬取完毕,爬虫会出现空跑问题,
我们可以修改scrapy-redis 源文件里面的,这里有两种修改方式
# schedluer.py
def next_request(self):
block_pop_timeout = self.idle_before_close
request = self.queue.pop(block_pop_timeout)
if request and self.stats:
self.stats.inc_value('scheduler/dequeued/redis', spider=self.spider)
if request is None:
self.spider.crawler.engine.close_spider(self.spider, 'queue is empty')
return request
# 当然也可以在scrapy_redis中spiders.py模块
def next_requests(self):
"""Returns a request to be scheduled or none."""
use_set = self.settings.getbool('REDIS_START_URLS_AS_SET', defaults.START_URLS_AS_SET)
fetch_one = self.server.spop if use_set else self.server.lpop
# XXX: Do we need to use a timeout here?
found = 0
# TODO: Use redis pipeline execution.
while found < self.redis_batch_size:
data = fetch_one(self.redis_key)
if not data:
# Queue empty.
print('+++++queue is empty')
self.crawler.engine.close_spider(self.spider, 'queue is empty')
break
req = self.make_request_from_data(data)
if req:
yield req
found += 1
else:
self.logger.debug("Request not made from data: %r", data)
if found:
self.logger.debug("Read %s requests from '%s'", found, self.redis_key)
参考: https://segmentfault.com/a/1190000014333162?utm_source=channel-hottest