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

Scrapy结合Celery报错:无法序列化本地lambda对象求解决方案

解决Celery中运行Scrapy多进程爬虫的Pickle错误

报错原因

Scrapy的Crawler类初始化时生成了lambda匿名函数,而Celery默认使用pickle序列化任务参数/对象,lambda属于无法被pickle序列化的本地对象,这就是触发Can't pickle local object 'Crawler.__init__.<locals>.<lambda>'错误的核心原因。

可行解决方法

方法1:切换Celery的序列化方式到cloudpickle

cloudpickle支持序列化lambda这类pickle搞不定的对象,步骤如下:

  1. 安装依赖:pip install cloudpickle
  2. 修改Celery配置,替换序列化器:
    from celery import Celery
    
    app = Celery('scrapy_tasks')
    app.conf.update(
        task_serializer='cloudpickle',
        result_serializer='cloudpickle',
        accept_content=['application/json', 'application/x-cloudpickle'],
    )
    
    注意:集群中所有Celery Worker都要安装cloudpickle,保证环境一致。

方法2:不在Celery任务间传递Crawler对象

最稳妥的方式是只在Celery任务内部初始化Scrapy的CrawlerProcess和爬虫,任务参数只传爬虫名称、配置字典这类可序列化的数据。示例代码:

from celery import Celery
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

app = Celery('scrapy_tasks')

@app.task
def run_spider(spider_name, custom_settings=None):
    # 加载Scrapy项目配置
    settings = get_project_settings()
    if custom_settings:
        settings.update(custom_settings)
    # 任务内部创建CrawlerProcess,完全避开序列化问题
    process = CrawlerProcess(settings)
    process.crawl(spider_name)
    process.start()

调用任务时只传简单参数:run_spider.delay('my_spider', {'CONCURRENT_REQUESTS': 10})

方法3:修改Scrapy源码替换lambda(不推荐)

如果必须传递Crawler对象,可以修改Scrapy的Crawler.__init__方法,把里面的lambda替换为顶层定义的可序列化函数。比如:
原Scrapy代码片段:

self.signals.connect(lambda _: self.stop(), signals.engine_stopped)

替换为:

def _on_engine_stopped(_):
    self.stop()
self.signals.connect(_on_engine_stopped, signals.engine_stopped)

这种方法侵入性极强,Scrapy版本升级后会失效,仅适合特殊场景。

额外提醒

  • 确保Celery Worker启动时,Scrapy项目的配置文件路径正确,能正常加载settings。
  • 多进程爬虫的并发配置(比如Scrapy的CONCURRENT_REQUESTS)要和Celery Worker的并发数合理搭配,避免资源耗尽。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:30:07