Scrapy多进程启动爬虫无响应及ReactorNotRestartable报错如何解决
问题原因
- Twisted的reactor是单例且不可重启的,你第一次调用
runner.start(stop_after_crawl=True)跑完cat_1之后,reactor已经被销毁,后续再调用同一个runner的start方法就会抛出ReactorNotRestartable错误。 - 你在主进程创建的全局
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
相关产品推荐
相关产品推荐

