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

Scrapy多进程启动爬虫无响应及ReactorNotRestartable报错如何解决

问题原因
  1. Twisted的reactor是单例且不可重启的,你第一次调用runner.start(stop_after_crawl=True)跑完cat_1之后,reactor已经被销毁,后续再调用同一个runner的start方法就会抛出ReactorNotRestartable错误。
  2. 你在主进程创建的全局runner对象传递到子进程时,内部关联的reactor状态已经异常,且你没有在子进程内启动事件循环,所以cat_2没有实际运行,爬取数据为0。
修复方案

核心逻辑是每个子进程独立初始化Scrapy运行环境,不复用主进程的CrawlerProcess和reactor对象,修改后的代码如下:

from multiprocessing import Process
from scrapy.crawler import CrawlerProcess
from scrapy.settings import Settings
import default_settings # 替换为你自己的配置模块

def launch_crawler_cat_2(crawler_cls, url):
    # 子进程内独立创建设置和CrawlerProcess,每个进程持有独立的reactor
    crawler_settings = Settings()
    crawler_settings.setmodule(default_settings)
    runner = CrawlerProcess(settings=crawler_settings)
    cat_name = url[0]
    cat_url = url[1]
    
    runner.crawl(crawler_cls, cat_name=cat_name, cat_url=cat_url)
    # 单独启动当前子进程的reactor,不会和主进程冲突
    runner.start(stop_after_crawl=True)

def process_cat_2(url_list):
    nb_spiders = len(url_list)
    list_process = [None] * nb_spiders
    
    while(url_list):
        for i in range(nb_spiders):
            if not (list_process[i] and list_process[i].is_alive()):
                # 传入cat_2爬虫类,不要传提前初始化的爬虫实例
                list_process[i] = Process(target=launch_crawler_cat_2, args=(cat_2, url_list.pop(0)))
                list_process[i].start()

    for process in list_process:
        if process:
            process.join()
注意事项
  • 所有Scrapy运行相关的初始化操作(设置加载、CrawlerProcess创建、爬虫实例化)都放在子进程内部完成,避免跨进程传递Twisted相关对象导致状态异常。
  • 确认cat_2爬虫类的__init__方法正确接收cat_name和cat_url参数,参数名需和runner.crawl传入的关键字参数保持一致。
  • 如果要降低进程开销,也可以使用CrawlerRunner配合异步回调在同一个子进程内运行多个爬虫任务,不需要每个URL单独开进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:39:04