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

如何将Scrapy爬取数据存入变量而非文件/数据库并按需调用

实现方法

你现有代码的问题是多进程封装仅做了异常传递,没有把爬虫产出的爬取结果从子进程回传到主进程,因此调用时拿不到数据。只要做两处调整即可实现「调用即触发爬虫、直接在内存处理爬取结果、无需落盘存储」的需求:

  1. 给爬虫注册一个内存级的临时Item Pipeline,所有Spider yield的item直接暂存到内存列表,不配置任何文件/数据库存储的Pipeline
  2. 修改多进程队列的传递逻辑,把爬取完成后收集到的结果随队列返回主进程,调用函数时直接拿到结果对象

完整可运行代码

import scrapy
import scrapy.crawler as crawler
from scrapy.utils.log import configure_logging
from multiprocessing import Process, Queue
from twisted.internet import reactor

# 原有Spider逻辑无需修改
class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = ['http://quotes.toscrape.com/tag/humor/']

    def parse(self, response):
        yield {"html_data": response.text}


def run_spider(spider_cls):
    def _crawl_in_subprocess(q):
        try:
            collected_items = []
            # 临时Pipeline:仅做内存收集,不做任何落盘操作
            class MemoryCollectPipeline:
                def process_item(self, item, spider):
                    collected_items.append(dict(item))
                    return item

            # 初始化Runner时仅注册内存收集Pipeline,禁用所有默认存储逻辑
            runner = crawler.CrawlerRunner(settings={
                "ITEM_PIPELINES": {
                    "__main__._crawl_in_subprocess.<locals>.MemoryCollectPipeline": 100
                }
            })
            deferred = runner.crawl(spider_cls)
            deferred.addBoth(lambda _: reactor.stop())
            reactor.run()
            # 爬取完成后把结果传回主进程
            q.put({"items": collected_items, "error": None})
        except Exception as e:
            q.put({"items": None, "error": e})

    msg_queue = Queue()
    crawl_process = Process(target=_crawl_in_subprocess, args=(msg_queue,))
    crawl_process.start()
    process_result = msg_queue.get()
    crawl_process.join()

    if process_result["error"]:
        raise process_result["error"]
    # 直接返回爬取到的所有结构化数据
    return process_result["items"]


if __name__ == "__main__":
    configure_logging()
    # 调用函数即触发爬虫运行,直接拿到所有爬取结果
    crawl_result = run_spider(QuotesSpider)
    # 直接在内存处理数据,无需读写文件/数据库
    print(f"爬取完成,共获取{len(crawl_result)}条数据")
    for single_item in crawl_result:
        print(f"单条页面HTML长度:{len(single_item['html_data'])}")

注意事项

  • 所有启动逻辑必须放在if __name__ == "__main__":代码块内,避免Windows平台多进程递归启动的报错,跨平台运行稳定性更好
  • 该封装支持重复调用,每次调用run_spider都会启动独立子进程运行爬虫,规避了Twisted reactor无法在同进程内重复启动的问题
  • 如果需要给爬虫传参(比如自定义爬取页码、起始URL),直接在runner.crawl(spider_cls, key=value)位置传入参数即可,和Scrapy原生传参逻辑完全一致
  • 爬取的数据量极大时不建议用这个方案,内存占用会随爬取数据量上涨,普通小规模爬取、实时处理场景完全适用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:15:41