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

Scrapy技术问题:自定义Item Pipeline后Feed Exports无数据输出?

问题:启用去重Pipeline后Scrapy Feed无数据写入

相关代码

Spider代码

class ExampleSpider(scrapy.Spider):
    name = 'example'

    custom_settings = {
        'ITEM_PIPELINES': {'img_clear.pipelines.DuplicatesPipeline': 100,},
        'FEEDS': {
            'feeds/example/tags.csv': {
                'format': 'csv',
                'fields': ["tag_id", "url", "title"],
                'item_export_kwargs': {
                    'include_headers_line': False,
                },
                'item_classes': [ExampleTagItem],
                'overwrite': False
            },
            'feeds/example/galleries.csv': {
                'format': 'csv',
                'fields': ["id", "url", "tag_ids"],
                'item_export_kwargs': {
                    'include_headers_line': False,
                },
                'item_classes': [ExampleGalleryItem],
                'overwrite': False,
            }
        }
    }

去重Pipeline代码

class DuplicatesPipeline():
    def open_spider(self, spider):
        if spider.name == "example":
            with open("feeds/example/galleries.csv", "r") as rf:
                csv = rf.readlines()
            self.ids_seen = set([str(line.split(",")[0]) for line in csv])
            
            with open("feeds/example/tags.csv", "r") as rf:
                tags_csv = rf.readlines()
            self.tag_ids_seen = set([str(line.split(",")[0]) for line in tags_csv])

    def process_item(self, item, spider):
        if isinstance(item, ExampleTagItem):
            self.process_example_tag_item(item, spider)    
        elif isinstance(item, ExampleGalleryItem):
            self.process_example_gallery_item(item, spider)

    def process_example_tag_item(self, item, spider):
        adapter = ItemAdapter(item)
        if adapter['tag_id'] in self.tag_ids_seen:
            raise DropItem(f"Duplicate item found: {item!r}")
        else:
            self.tag_ids_seen.add(adapter['tag_id'])
            return item

    def process_example_gallery_item(self, item, spider):
        adapter = ItemAdapter(item)
        if adapter['id'] in self.ids_seen:
            raise DropItem(f"Duplicate item found: {item!r}")
        else:
            self.ids_seen.add(adapter['id'])
            return item

现象与排查信息

  • 启用Pipeline后,日志显示已丢弃重复项,也能抓取到有效项,但Feed文件始终无数据写入;
  • 注释掉ITEM_PIPELINES配置后,数据可正常写入CSV;
  • 启用Pipeline时执行scrapy crawl example -o test.csv,生成的CSV为空;
  • 在Pipeline返回Item前打印内容,显示正常。

问题原因与解决办法

核心原因

DuplicatesPipeline的process_item方法没有返回处理后的Item。Scrapy的Pipeline是链式执行的,每个process_item必须返回Item对象(或抛出DropItem),否则后续环节(包括Feed Exports扩展)接收不到数据。你的代码只是调用了子处理方法,但没把子方法的返回值传递下去,相当于默认返回None,导致Feed扩展拿不到有效数据。

修复代码

修改process_item方法,添加返回逻辑:

def process_item(self, item, spider):
    if isinstance(item, ExampleTagItem):
        return self.process_example_tag_item(item, spider)    
    elif isinstance(item, ExampleGalleryItem):
        return self.process_example_gallery_item(item, spider)
    # 兜底返回,避免漏处理的情况
    return item

验证说明

修改后,有效Item会被正常返回给后续环节,Feed Exports就能接收到数据并写入文件;重复项依然会被DropItem抛出,日志也会正常显示丢弃信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:35:21