You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Python Scrapy请求队列的请求数?遇返回值异常问题

Scrapy请求队列计数异常问题解析

问题现象

  • 调用 len(self.crawler.engine.slot.scheduler) 始终返回0,无法获取当前队列请求数
  • 读取 self.crawler.engine.slot.scheduler.stats._stats['scheduler/enqueued'] 得到的是持续递增的累计值(1、2…10),和预期中“队列初始值高、随爬取递减”的逻辑不符
  • 开启翻页请求后,队列统计值持续递增,即使已配置 CONCURRENT_REQUESTS = 1

核心原因

  1. len(scheduler) 无效的本质
    Scrapy的Scheduler类本身没有实现__len__魔法方法,直接对其调用len()会返回默认值0,这种方式根本无法获取当前待处理请求数。

  2. scheduler/enqueued 是累计值而非剩余值
    这个统计项记录的是爬虫启动以来所有入队请求的总数,包括已经处理完成的请求,因此只会持续递增,不会随请求处理而减少,和你需要的“当前队列剩余请求数”不是同一个概念。

  3. 翻页请求重复入队
    你在遍历每个quote的循环内部判断并生成翻页请求,导致同一个页面的next_page被重复入队多次(每个quote对应一次),直接造成累计入队数暴涨。

解决方法与修正代码

1. 正确获取当前队列剩余请求数

访问调度器内部的queue属性(默认调度器使用PriorityQueue),通过len(queue)获取剩余待处理请求数。注意这是内部属性,不同Scrapy版本或自定义调度器可能有差异。

2. 修正翻页请求逻辑

将翻页请求的判断与生成移到遍历quote的循环外部,避免重复入队。

修正后的代码

import scrapy

class QuotesSpider(scrapy.Spider):
    name = "quotes_spider"
    start_urls = [
        f"https://quotes.toscrape.com/page/{i}/" for i in range(1, 11)
    ]
    custom_settings = {
        "CONCURRENT_REQUESTS": 1
    }

    def parse(self, response):
        # 获取当前队列剩余请求数
        try:
            queue_size = len(self.crawler.engine.slot.scheduler.queue)
        except AttributeError:
            queue_size = "无法获取(调度器队列类型不支持)"
        
        # 用官方Stats API获取累计入队数,而非直接访问私有属性
        total_enqueued = self.crawler.stats.get_value("scheduler/enqueued", 0)
        
        print(f"\n处理页面: {response.url}")
        print(f"当前队列剩余请求数: {queue_size}")
        print(f"累计入队请求数: {total_enqueued}\n")

        # 解析quote数据
        for quote in response.css("div.quote"):
            yield {
                "text": quote.css("span.text::text").get(),
                "author": quote.css("small.author::text").get(),
                "tags": quote.css("div.tags a.tag::text").getall(),
            }
        
        # 翻页逻辑移到循环外,避免重复入队
        next_page = response.css("li.next a::attr(href)").get()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)

额外说明

  • 不建议直接访问scheduler.stats._stats这种私有属性,使用self.crawler.stats.get_value()是更规范的方式,兼容性更好。
  • 如果使用第三方调度器(如RedisScheduler),队列属性名称可能不同,需要对应调整获取方式。

内容的提问来源于stack exchange,提问作者Aananda Giri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:34:54