如何同时运行带有不同CrawlerRunner配置的Scrapy爬虫?
正确实现方式
问题根源
你的代码无法运行的核心问题有两个:
- 为每个爬虫的
crawl()结果都绑定了reactor.stop(),导致第一个爬虫执行完毕就立刻终止Twisted reactor,后续爬虫根本没有启动的机会。 - 完全不需要创建多个
CrawlerRunner实例,单个CrawlerRunner就可以同时管理多个带有不同配置的爬虫。
方案一:单个CrawlerRunner + 爬虫独立配置(推荐)
利用CrawlerRunner.crawl()方法的settings参数,为每个爬虫单独指定FEEDS配置,覆盖全局设置。这样既简洁又能保证所有爬虫并行执行,直到全部完成再停止reactor。
示例代码:
import scrapy from twisted.internet import reactor from scrapy.crawler import CrawlerRunner from scrapy.utils.log import configure_logging from scrapy.utils.project import get_project_settings # 假设你的爬虫定义如下 class Live1(scrapy.Spider): name = "live1" # 你的爬虫逻辑... class Live2(scrapy.Spider): name = "live2" # 你的爬虫逻辑... class Live3(scrapy.Spider): name = "live3" # 你的爬虫逻辑... configure_logging() # 获取项目全局设置,也可以直接用空字典自定义基础设置 base_settings = get_project_settings() runner = CrawlerRunner(base_settings) # 为每个爬虫单独传入FEEDS配置 runner.crawl(Live1, settings={ "FEEDS": { r"C:\Users\Messi\1.json": {"format": "json", "overwrite": True} } }) runner.crawl(Live2, settings={ "FEEDS": { r"C:\Users\Messi\2.json": {"format": "json", "overwrite": True} } }) runner.crawl(Live3, settings={ "FEEDS": { r"C:\Users\Messi\3.json": {"format": "json", "overwrite": True} } }) # 等待所有爬虫完成后再停止reactor d = runner.join() d.addBoth(lambda _: reactor.stop()) reactor.run()
注意点:
- FEEDS路径可以不用
file://协议,直接用本地绝对路径更简洁(Windows下注意转义,或者用原始字符串r"")。 get_project_settings()会加载项目的settings.py配置,如果不需要全局配置,也可以直接传入{}作为基础设置。
方案二:多个CrawlerRunner(不推荐)
如果一定要使用多个CrawlerRunner实例,需要将所有爬虫的Deferred对象合并,统一在全部完成后再停止reactor,而不是每个单独绑定stop操作。
示例代码:
import scrapy from twisted.internet import reactor, defer from scrapy.crawler import CrawlerRunner from scrapy.utils.log import configure_logging class Live1(scrapy.Spider): name = "live1" # 爬虫逻辑... class Live2(scrapy.Spider): name = "live2" # 爬虫逻辑... class Live3(scrapy.Spider): name = "live3" # 爬虫逻辑... configure_logging() runner1 = CrawlerRunner(settings={ "FEEDS": {r"C:\Users\Messi\1.json": {"format": "json", "overwrite": True}} }) runner2 = CrawlerRunner(settings={ "FEEDS": {r"C:\Users\Messi\2.json": {"format": "json", "overwrite": True}} }) runner3 = CrawlerRunner(settings={ "FEEDS": {r"C:\Users\Messi\3.json": {"format": "json", "overwrite": True}} }) # 收集所有爬虫的Deferred对象 deferreds = [ runner1.crawl(Live1), runner2.crawl(Live2), runner3.crawl(Live3) ] # 合并所有Deferred,全部完成后停止reactor d = defer.gatherResults(deferreds) d.addBoth(lambda _: reactor.stop()) reactor.run()
为什么不推荐这个方案?
多个CrawlerRunner会初始化多个独立的配置环境,增加不必要的资源开销,而且单个CrawlerRunner完全能满足需求,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者user19925544
相关产品推荐
相关产品推荐

