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

如何将Scrapy抓取的单个元素拆分至CSV多行?

解决Scrapy导出CSV时每个Genre单独一行的问题

嘿,我太懂这种明明XPath已经精准拿到了genre列表,却卡在CSV输出格式上的挫败感了——试了一堆方案还是没搞定基础功能,确实闹心!下面给你两种靠谱的解决思路,都是我实际项目里用过的:

方法一:在Spider里直接拆分生成单个Item(推荐)

这是最直接的方式,在解析页面的时候,就把每个genre对应成一个独立的Item,这样后续导出CSV自然就是每行一个类型。

假设你的Item定义是这样的:

import scrapy

class MovieItem(scrapy.Item):
    title = scrapy.Field()
    release_year = scrapy.Field()
    genre = scrapy.Field()  # 注意这里是单个类型,不是列表

那在Spider的parse函数里,遍历拿到的genre列表,逐个生成Item:

def parse(self, response):
    # 先抓取其他固定字段
    movie_title = response.xpath('//h1[@class="movie-title"]/text()').get().strip()
    release_year = response.xpath('//span[@class="release-year"]/text()').get().strip()
    
    # 通过XPath获取完整的genre列表
    genre_list = response.xpath('//div[@class="genre-container"]/a/text()').getall()
    
    # 遍历每个genre,生成单独的Item
    for genre in genre_list:
        item = MovieItem()
        item['title'] = movie_title
        item['release_year'] = release_year
        item['genre'] = genre.strip()  # 单个类型值
        yield item

这样Scrapy默认的CSV导出器就能直接输出每行一个genre的结果,不需要额外修改Pipeline。

方法二:在Pipeline中拆分Item(适合已有的Spider不想大改的情况)

如果你的Spider已经输出了带genre列表的Item,不想改动Spider代码,可以在Pipeline里做拆分处理:

首先,自定义一个Pipeline类,负责拆分带列表的Item并导出:

from scrapy.exporters import CsvItemExporter

class GenreSplitPipeline:
    def open_spider(self, spider):
        # 打开CSV文件并初始化导出器
        self.csv_file = open('movies_with_genres.csv', 'wb')
        self.exporter = CsvItemExporter(self.csv_file)
        self.exporter.start_exporting()

    def close_spider(self, spider):
        self.exporter.finish_exporting()
        self.csv_file.close()

    def process_item(self, item, spider):
        # 检查Item里是否有genre列表字段
        if 'genres' in item and isinstance(item['genres'], list):
            # 遍历每个genre,生成新的Item并导出
            for genre in item['genres']:
                split_item = item.copy()
                split_item['genre'] = genre.strip()
                del split_item['genres']  # 删除原列表字段
                self.exporter.export_item(split_item)
        else:
            # 如果没有列表,直接导出原Item
            self.exporter.export_item(item)
        return item

然后在settings.py里启用这个Pipeline,记得注释掉默认的CSV导出器:

ITEM_PIPELINES = {
    # 'your_project_name.pipelines.YourDefaultPipeline': 300,
    'your_project_name.pipelines.GenreSplitPipeline': 300,
}

关键注意事项

  • 确保Item里的字段是单个值类型,不要用列表字段导出,否则默认CSV会把列表转成逗号分隔的字符串(比如Mystery,Comedy),不是你想要的每行一个。
  • 如果用方法一,记得把Item里的genre字段定义为单个值,而不是列表。

我之前处理电影类型导出时也踩过同样的坑,一开始总想在Pipeline里绕弯路,后来发现直接在Spider里拆分Item最省心,你可以试试这两种方法,应该能解决你的问题!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:20:43