刮擦请求.优先级不起作用



官方文档对scrapy.Request.priority解释如下:

优先级 (int)– 此请求的优先级(默认为 0)。调度程序使用优先级来定义用于处理请求的顺序。具有较高优先级值的请求将更早执行。允许使用负值以指示相对较低的优先级。

但我的测试不是那样的:
scrapy version: 2.6.2
Python version: 3.7.13

class TestSpider(scrapy.Spider):
name = 'test'
custom_settings = {
'DOWNLOAD_DELAY': 5,
'CONCURRENT_REQUESTS': 1
}
def start_requests(self):
urls = {
10: 'https://www.baidu.com/s?wd=111111',
20: 'https://www.baidu.com/s?wd=222222',
30: 'https://www.baidu.com/s?wd=333333'  # this url may pass to the first request?
}
for index, url in urls.items():
yield scrapy.Request(url,
headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
},
callback=self.parse,
priority=index,  # <- check here!!
meta={'priority': index},
dont_filter=True)
def parse(self, response, **kwargs):
self.log(datetime.datetime.now().strftime('%H:%M:%S'))
self.log(response.request.url)
title = response.xpath('//title/text()').get()
self.log(title)

在爬虫日志之后,请求顺序始终保持如下:

2022-07-26 16:16:10 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.baidu.com/s?wd=111111> (referer: None)
2022-07-26 16:16:10 [test] DEBUG: 16:16:10
2022-07-26 16:16:10 [test] DEBUG: https://www.baidu.com/s?wd=111111
2022-07-26 16:16:10 [test] DEBUG: 111111_百度搜索
2022-07-26 16:16:15 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.baidu.com/s?wd=222222> (referer: None)
2022-07-26 16:16:15 [test] DEBUG: 16:16:15
2022-07-26 16:16:15 [test] DEBUG: https://www.baidu.com/s?wd=222222
2022-07-26 16:16:15 [test] DEBUG: 222222_百度搜索
2022-07-26 16:16:20 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.baidu.com/s?wd=333333> (referer: None)
2022-07-26 16:16:20 [test] DEBUG: 16:16:20
2022-07-26 16:16:20 [test] DEBUG: https://www.baidu.com/s?wd=333333
2022-07-26 16:16:20 [test] DEBUG: 333333_百度搜索
2022-07-26 16:16:20 [scrapy.core.engine] INFO: Closing spider (finished)

当从start_requests方法生成请求时,它会立即传递给 scrapy 引擎,然后传递给调度程序。 如果调度程序的优先级队列中没有任何以前生成的请求,那么它将在 reactor 事件循环的下一次迭代时立即执行。

在第一次初始化一个刮擦蜘蛛时,会构造一个新的空调度程序,因此提供给start_requests方法调度器的第一个请求将始终是引擎执行的第一个请求。由于start_requests方法一次生成一个请求,因此无论优先级如何,它们都可能以相同的顺序执行,因为调度程序不知道存在具有更高优先级的后续请求。

这是指向scrapy文档概述的链接,该概述描述了scrapy工作流程的分步过程。


问题的解决方案是在从start_requests方法生成 url 之前,根据其优先级对 url 进行排序。

例如:

def start_requests(self):
urls = {10: 'https://www.baidu.com/s?wd=111111',
20: 'https://www.baidu.com/s?wd=222222',
30: 'https://www.baidu.com/s?wd=333333'}
for index, url in sorted(urls.items(), reverse=True):
yield scrapy.Request(url, callback=self.parse, priority=index, ...)

最新更新