ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Scrapy 如何在同一进程内并行或顺序运行多个 spider?AsyncCrawlerProcess 与 AsyncCrawlerRunner 用法

2026/9/15 16:18:31 拓冰建站 浏览量
Scrapy 如何在同一进程内并行或顺序运行多个 spider?AsyncCrawlerProcess 与 AsyncCrawlerRunner 用法 Scrapy 如何在同一进程内并行或顺序运行多个 spiderAsyncCrawlerProcess 与 AsyncCrawlerRunner 用法【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy默认情况下scrapy crawl每次只在一个进程中运行一个 spider。Scrapy 的内部 API 支持在同一个进程内运行多个 spider每次调用crawl()都会创建一个独立的Crawler对象拥有各自的 downloader、spider middleware 和已解析的设置包括 spider 级设置不同 spider 之间互不共享。完成这个任务有两个入口类AsyncCrawlerProcess和AsyncCrawlerRunner两者都提供基于协程的 API对应的 Deferred 风格旧版是CrawlerProcess/CrawlerRunner。两个入口类的适用条件选择哪个类取决于你的脚本是否已经有事件循环AsyncCrawlerProcess会自己启动 Twisted reactor 或 asyncio 事件循环并配置日志、安装 Ctrl-C 等关闭信号处理器。当你没有在应用中运行其他 reactor 时用它。它的start()是阻塞调用直到爬取结束才返回。AsyncCrawlerRunner只是对多个 crawler 的薄封装不会启动或干扰已有的 reactor。当你的应用已经使用 Twisted、希望在同一个 reactor 内运行 Scrapy 时应选它。注意两点前提当TWISTED_REACTOR_ENABLED为True默认时要求已安装twisted.internet.asyncioreactor.AsyncioSelectorReactor当设置为False时要求进程中没有安装 Twisted reactor但已安装 asyncio 事件循环。在 Scrapy 项目内运行时还可以把 spider 名字符串传给crawl()由 spider loader 自动加载项目设置可用scrapy.utils.project.get_project_settings获取作为AsyncCrawlerProcess构造参数传入。用 AsyncCrawlerProcess 并行运行多个 spiderAsyncCrawlerProcess下并行最简单连续调用多次crawl()后再start()脚本会阻塞直到所有爬取任务结束。以下示例来自官方文档其中MySpider1/MySpider2需替换为你自己的 spider 类import scrapy from scrapy.crawler import AsyncCrawlerProcess from scrapy.utils.project import get_project_settings class MySpider1(scrapy.Spider): # 第一个 spider 的定义 ... class MySpider2(scrapy.Spider): # 第二个 spider 的定义 ... settings get_project_settings() process AsyncCrawlerProcess(settings) process.crawl(MySpider1) process.crawl(MySpider2) process.start() # 阻塞直到所有爬取任务结束判断完成的依据start()文档说明其为阻塞调用当stop_after_crawlTrue默认时所有 crawler 结束后 reactor/事件循环会停止并返回。如果你需要程序化地等待crawl()返回的asyncio.Task在该 spider 爬取完成时结束也可以调用join()所有受管 crawler 完成时结束或stop()同时停止所有爬取任务全部结束后完成。用 AsyncCrawlerRunner 并行运行当脚本需要自己管理 reactor 时用AsyncCrawlerRunner。并行写法是把两个crawl()的返回值都不等待最后await runner.join()两个 spider 同时跑、都结束后才往下执行。以下示例直接取自 docs/topics/practices.rstMySpider1/MySpider2需替换为你自己的 spider 类import scrapy from scrapy.crawler import AsyncCrawlerRunner from scrapy.utils.defer import deferred_f_from_coro_f from scrapy.utils.log import configure_logging from scrapy.utils.reactor import install_reactor from twisted.internet.task import react class MySpider1(scrapy.Spider): # 第一个 spider 的定义 ... class MySpider2(scrapy.Spider): # 第二个 spider 的定义 ... async def crawl(_): configure_logging({LOG_FORMAT: %(levelname)s: %(message)s}) runner AsyncCrawlerRunner() runner.crawl(MySpider1) runner.crawl(MySpider2) await runner.join() # 两个 spider 都结束后才完成 install_reactor() react(deferred_f_from_coro_f(crawl))这里的顺序要点configure_logging要在创建 runner 前调用因为AsyncCrawlerRunner本身不配置日志install_reactor()必须先于crawl()调用否则crawl()会抛出RuntimeError文档中给出的报错信息为 We expected a Twisted reactor to be installed but it isnt.。仓库测试脚本 tests/AsyncCrawlerRunner/multi_parallel.py 是同一模式的实际用例。用 AsyncCrawlerRunner 顺序运行多个 spider顺序执行只需对每次crawl()逐一await前一个 spider 完成后后一个才开始。同样来自 docs/topics/practices.rstimport scrapy from scrapy.crawler import AsyncCrawlerRunner from scrapy.utils.defer import deferred_f_from_coro_f from scrapy.utils.log import configure_logging from scrapy.utils.reactor import install_reactor from twisted.internet.task import react class MySpider1(scrapy.Spider): # 第一个 spider 的定义 ... class MySpider2(scrapy.Spider): # 第二个 spider 的定义 ... async def crawl(_): configure_logging({LOG_FORMAT: %(levelname)s: %(message)s}) runner AsyncCrawlerRunner() await runner.crawl(MySpider1) await runner.crawl(MySpider2) install_reactor() react(deferred_f_from_coro_f(crawl))对应测试脚本见 tests/AsyncCrawlerRunner/multi_seq.py。AsyncCrawlerProcess也可以做到顺序语义文档示例展示了在TWISTED_REACTOR_ENABLEDFalse时在同一进程内先后创建两个AsyncCrawlerProcess实例并各自start()前一个start()返回即爬取结束后才执行第二个。多 spider 同进程的限制以下几点直接来自文档决定你的配置方式日志设置和 reactor 设置不应因 spider 不同而取不同值pre-crawler 设置不能按 spider 分别定义。AsyncCrawlerProcess检测到后续 crawler 的 reactor 设置DNSCACHE_ENABLED、DNS_RESOLVER等与第一个 crawler 不一致时会发出警告并只使用第一个 spider 的值因为 reactor 被同进程所有 spider 共享见 scrapy/crawler.py 的create_crawler。其余所有设置包括并发与礼貌设置CONCURRENT_REQUESTS、CONCURRENT_REQUESTS_PER_DOMAIN、DOWNLOAD_DELAY都独立作用于每个 crawlerAutoThrottle 也分别对每个 crawler 限速。因此并行运行时文档建议把这些值除以 crawler 数量以保持对硬件和目标站点的总负载不变。由此推论在同一进程里把同一个 spider 跑多份并不会提升抓取能力只会乘倍地占满这些限额要爬得更快应在单个 crawler 上提高CONCURRENT_REQUESTS。Crawler.crawl()/crawl_async()每个 crawler 实例只能调用一次engine、extensions、stats等属性在爬取开始前读取会抛RuntimeError见 scrapy/crawler.py。如果你要在已有应用内而非独立脚本运行 spiderdocs/topics/practices.rst 的 Running spiders inside existing applications 一节给出了按应用类型已有 Twisted reactor、WSGI、ASGI的选择建议可与本文的 runner/process 用法对照使用。【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考