前言:
终于找到机会,开始把scrapy-redis细致地给大伙通一通了! 为什么非要细致讲scrapy-redis呢?
- 1.市面上关于scrapy-redis的教程,都比较笼统; demo级别好写,但是一旦上了项目,就问题百出!
- 2.scrapy-redis里面的思路,其实跟单个爬虫或者集合式爬虫他的思路有点不一样;
正文:
在使用Scrapy-Redis进行Scrapy分布式爬虫时,Redis中会出现一些特定的key,用于存储爬虫在运行过程中所需的数据。其中两个重要的key是"爬虫名:dupefilter"和"爬虫名:requests"。
-
"爬虫名:dupefilter":
- 功能:该key用于存储去重集合,用来避免在分布式爬取过程中重复请求相同的URL。
- 工作原理:当爬虫向Redis请求队列添加一个新的请求时,它会先检查该请求是否已经存在于去重集合中。如果已经存在,则该请求会被忽略,不会再次被添加到队列中。如果该请求不存在于去重集合中,才会将其加入待抓取队列,并将其标记在去重集合中,以避免未来重复抓取。
-
"爬虫名:requests":
- 功能:该key用于存储待抓取请求队列,实际上是一个列表结构。
- 工作原理:所有从spider发出且尚未被执行的Requests都会被序列化后存储在这个列表中。Scrapy-Redis的爬虫实例会不断从这个队列中取出Requests来执行。当一个Requests被取出并由某个爬虫实例成功抓取后,它就会从队列中移除。这样,即使有多个爬虫实例在运行,它们可以共享这个请求队列,实现分布式爬取的效果。
通过合理使用这两个key,Scrapy-Redis能够实现分布式爬虫的高效并发和去重处理。通过去重集合的机制,避免了重复请求相同的URL,提高了爬取效率。同时,利用请求队列的机制,多个爬虫实例可共享相同的待抓取请求,实现分布式集群化爬取,进一步加速数据采集过程。
案例说明:
spider.py
import scrapy
from scrapy_redis.spiders import RedisSpiderclass MySpider(RedisSpider):name = 'my_spider' # 爬虫名称allowed_domains = ['example.com'] # 允许爬取的域名列表def parse(self, response):# 解析响应数据的代码逻辑# ...# 获取详情页URLdetail_urls = response.xpath('//a[@class="detail-link"]/@href').getall()# 将解析到的详情页URL加入Redis请求队列for url in detail_urls:yield scrapy.Request(url, callback=self.parse_detail)def parse_detail(self, response):# 解析详情页面的代码逻辑# ...def make_request_from_data(self, data):url = data.decode('utf-8')return scrapy.Request(url, callback=self.parse_detail)def start_requests(self):# 起始URLurl = 'http://example.com'yield scrapy.Request(url, callback=self.parse)def redis_key(self, spider):# 设置Redis key为 "jihaiend2:requests"return f'{spider}:requests'
settings.py
REDIS_HOST = 'localhost' # Redis主机地址
REDIS_PORT = 6379 # Redis端口
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter' # 去重过滤器类
SCHEDULER = 'scrapy_redis.scheduler.Scheduler' # 调度器类
SCHEDULER_PERSIST = True # 设置为True,保持爬虫状态持久化
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 队列调度器类
main.pyfrom scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settingsspider = MySpider() # 创建爬虫实例
process = CrawlerProcess(get_project_settings()) # 创建爬虫进程
process.crawl(spider) # 添加爬虫到进程
process.start() # 启动爬虫进程进行爬取
对这两个keys的操作:
在Scrapy-Redis中,可以通过以下方式对 "dupefilter" 和 "requests" 这两个关键Key进行操作:
-
对 "dupefilter"(去重集合)的操作:
- 添加请求:在爬虫代码中,在发送请求之前,可以通过调用
request.dont_filter = False
来确保该请求被添加到去重集合中。 - 检查请求是否重复:Scrapy-Redis会自动检查请求的URL是否已经存在于去重集合中,如果存在,则认为该请求是重复的,不会被发送。这样可以避免重复请求相同的URL。
- 添加请求:在爬虫代码中,在发送请求之前,可以通过调用
-
对 "requests"(待抓取请求队列)的操作:
- 添加请求:在爬虫代码中,通过调用
yield scrapy.Request(url, callback=callback_function)
来将请求加入到Redis的请求队列中。其中url
是要抓取的URL,callback_function
是对应的回调函数,用于处理该请求的响应。 - 获取请求:爬虫实例会从Redis的请求队列中获取待抓取的请求,并将其分配给相应的回调函数进行处理。
- 处理请求:在回调函数中,可以对从请求队列中获取的请求进行解析、处理和提取数据等。
- 添加请求:在爬虫代码中,通过调用
通过上述操作,我们可以很方便地对这两个关键Key进行操作,实现分布式爬虫的去重和请求共享功能。Scrapy-Redis会自动处理 "dupefilter" 的去重机制和 "requests" 的请求队列,无需手动管理和操作。
如果你发现,你的redis里面并没有出现这两个keys,那么如何排查呢?
排查问题:
当 "dupefilter"(去重集合)和 "requests"(待抓取请求队列)这两个关键Key出现异常时,最可能的问题源头可以在以下几个方面:
-
配置错误:检查Scrapy-Redis的配置是否正确设置。确保在settings.py文件中正确配置了Redis的连接信息、去重过滤器、调度器和队列调度器等相关设置。
-
Redis连接问题:如果无法连接到Redis服务器,就无法正确使用这两个关键Key。检查Redis的主机地址、端口以及身份验证等连接参数是否正确,并确保Redis服务器正在运行。
-
网络通信问题:如果Scrapy爬虫无法与Redis服务器进行通信,可能是由于网络配置或防火墙等原因导致的。确保Redis服务器对Scrapy爬虫所在的机器可访问,并允许相应的端口通信。
-
错误的Key名称:如果 "dupefilter" 和 "requests" 的Key名称配置不正确,Scrapy-Redis将无法找到相应的Key,并可能导致异常。请确保将这两个Key的名称配置正确,并与Redis中对应的Key名称匹配。
-
异步任务处理问题:Scrapy-Redis通过异步任务处理请求队列和去重集合,在某些情况下,可能会有一些异步任务处理失败或超时。在这种情况下,需要检查和调整异步任务处理的相关设置,例如提高超时时间或增加异步任务处理的并发能力。
以上是一些常见的问题源头,可能导致 "dupefilter" 和 "requests" 这两个关键Key出现异常。在调试和排查问题时,应仔细检查并排除可能出现问题的这些方面,并确保正确配置和使用Scrapy-Redis的相关组件和功能。