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

如何组织多个Scrapy Spider并在不同Spider之间传递数据

方案解答

你当前在单Spider内为不同站点编写独立解析方法的实现,在仅需从A站跳转爬取B/C站内容的轻量场景下是可用的,逻辑链路连贯无需额外中间存储,开发成本很低。但确实存在B/C站解析逻辑和A站爬取流程强耦合的问题,无法满足你后续单独爬取B/C站的需求,不是长期维护的最优解。

下面给两种适配你需求的实现方案,可根据自己的使用场景选择:

方案1:抽离公共解析逻辑,兼顾单Spider便捷性和复用性

你可以把B、C站的解析逻辑完全抽成独立的公共函数/模块,和A站的爬取逻辑解耦,不管是A站跳转的请求还是单独爬B/C站的请求都可以直接调用,不需要重复写解析代码:

  1. 新建parsers目录,分别存放B站、C站的解析文件
    示例parsers/site_b.py代码:
def parse_site_b(response):
    return {
        "article_title": response.xpath('//p[contains(@class, "Header_desktopTextElement")]/text()').get(),
        "article_content": response.xpath('//div[contains(@class, "content")]//text()').getall()
        # 其他B站字段解析逻辑统一写在这里
    }
  1. 原有A站Spider直接导入解析函数使用:
from parsers.site_b import parse_site_b
from parsers.site_c import parse_site_c

class QuotesSpider(scrapy.Spider):
    name = 'Website A Spider'
    start_urls = ['start_url']

    def parse(self, response):
        important_news = response.xpath('//div[contains(@class, "importantNews")]//div[contains(@class, "items")]/a')
        for news in important_news:
            link = news.xpath('./@href').get()
            title = news.xpath('.//span[contains(@class, "title")]/text()').get()
            meta = {"source_title": title, "source_link": link}
            if 'Website B' in link:
                yield response.follow(link, callback=parse_site_b, meta=meta)
            elif 'Website C' in link:
                yield response.follow(link, callback=parse_site_c, meta=meta)
  1. 后续需要单独爬B站的时候,单独写个B站Spider直接调用相同的解析函数即可,逻辑完全复用。

方案2:完全拆分独立Spider,适合多场景灵活调用

如果你需要三个Spider完全独立,互不依赖,可以通过中间存储传递A站爬取到的链接和元数据:

  1. 先运行A站Spider,将爬取到的链接、标题等信息存储为JSON/CSV文件,或者存入数据库、Redis等介质
  2. 编写独立的B站、C站Spider,在start_requests方法中读取A站输出的链接作为爬取入口,通过meta参数传递A站拿到的元数据:
    示例B站独立Spider代码:
import json
import scrapy

class SiteBSpider(scrapy.Spider):
    name = "site_b"
    # 也可以通过命令行参数传入链接文件路径,灵活度更高
    def start_requests(self):
        with open("a_site_output.json", "r", encoding="utf-8") as f:
            a_items = json.load(f)
        for item in a_items:
            if "Website B" not in item["link"]:
                continue
            yield scrapy.Request(
                url=item["link"],
                callback=self.parse,
                # 传递A站拿到的元数据
                meta={"source_title": item["title"], "source_link": item["link"]}
            )
    
    def parse(self, response):
        # 合并元数据和B站解析结果
        result = {
            "source_title": response.meta["source_title"],
            "source_link": response.meta["source_link"]
        }
        # 调用之前抽离的公共解析逻辑,合并到结果中
        from parsers.site_b import parse_site_b
        result.update(parse_site_b(response))
        yield result

这种方案的优势是三个Spider完全解耦,后续单独爬B/C站的时候,只需要传入对应站点的链接列表即可,不需要再运行A站的爬取流程,某一个站点的规则变更也只需要修改对应Spider,维护成本更低。如果爬取量比较大,推荐将中间数据存在Redis或者SQLite中,方便做去重和断点续爬。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:45:04