如何将Scrapy Item导出至不同文件?附MOOC评论爬取代码片段
嘿,我来帮你搞定Scrapy Item导出到不同文件的事儿!你已经在爬MOOC的课程详情和评论了,下面这几种方法应该能完美适配你的需求:
这是Scrapy自带的核心功能,不用额外写复杂代码,直接在settings.py里配置就能实现分文件导出。
第一步:给Item加个区分标识
因为你要导出课程详情(5个字段)和评论(6个字段)两种数据,最好先给MoocsItem加个item_type字段,用来标记当前Item是课程还是评论。比如:# 在课程详情解析的parse_reviews方法里添加 def parse_reviews(self, response): l = ItemLoader(item=MoocsItem(), response=response) l.add_xpath('course_title', '//*[@class="course-header-ng__main-info__name__title"]//text()') l.add_xpath('course_description', '//*[@class="course-info__description"]//p/text()') l.add_xpath('course_instructors', '//*[...]') # 标记为课程类型 l.add_value('item_type', 'course') yield l.load_item() # 假设你有专门解析评论的方法,同样添加标记 def parse_comment(self, response): l = ItemLoader(item=MoocsItem(), response=response) # 填充你的6个评论字段 l.add_xpath('comment_author', '//*[...]') # ...其他评论字段 l.add_value('item_type', 'review') yield l.load_item()第二步:配置Feed规则
打开settings.py,添加FEEDS配置,通过item_filter过滤不同类型的Item,分别导出到对应文件:FEEDS = { 'courses.csv': { 'format': 'csv', 'item_filter': lambda item: item.get('item_type') == 'course', 'fields': ['course_title', 'course_description', 'course_instructors'] # 替换为你的5个课程字段 }, 'reviews.json': { 'format': 'json', 'item_filter': lambda item: item.get('item_type') == 'review', 'fields': ['comment_author', 'comment_content', 'comment_rating'] # 替换为你的6个评论字段 } }这样运行爬虫时,Scrapy会自动把课程数据导出到
courses.csv,评论数据导出到reviews.json,完全不用额外操作。
如果需要更复杂的导出逻辑(比如按课程ID拆分评论文件、导出特殊格式),可以写自定义的Item Pipeline:
第一步:编写Pipeline类
在pipelines.py里创建两个Pipeline,分别处理课程和评论的导出:import csv import json class CourseExportPipeline: def open_spider(self, spider): # 打开课程文件并初始化CSV写入器 self.file = open('courses.csv', 'w', newline='', encoding='utf-8') self.writer = csv.DictWriter(self.file, fieldnames=['course_title', 'course_description', 'course_instructors']) self.writer.writeheader() def process_item(self, item, spider): # 只处理课程类型的Item if item.get('item_type') == 'course': self.writer.writerow(item) # 一定要return item,让后续Pipeline继续处理 return item def close_spider(self, spider): self.file.close() class ReviewExportPipeline: def open_spider(self, spider): # 打开评论文件,先把Item存在列表里 self.file = open('reviews.json', 'w', encoding='utf-8') self.review_items = [] def process_item(self, item, spider): if item.get('item_type') == 'review': self.review_items.append(dict(item)) return item def close_spider(self, spider): # 爬虫结束时把所有评论写入JSON文件 json.dump(self.review_items, self.file, ensure_ascii=False, indent=2) self.file.close()第二步:启用Pipeline
在settings.py里添加ITEM_PIPELINES配置,指定要启用的Pipeline和优先级(数字越小越先执行):ITEM_PIPELINES = { '你的项目名.pipelines.CourseExportPipeline': 300, '你的项目名.pipelines.ReviewExportPipeline': 400, }替换
你的项目名为实际的Scrapy项目名称即可。
如果只是偶尔需要导出不同文件,不想改配置文件,可以直接用命令行参数指定:
# 导出课程数据到CSV scrapy crawl 你的爬虫名 --feed courses.csv:csv -s FEED_ITEM_FILTER="lambda item: item['item_type'] == 'course'" # 导出评论数据到JSON scrapy crawl 你的爬虫名 --feed reviews.json:json -s FEED_ITEM_FILTER="lambda item: item['item_type'] == 'review'"
不过这种方法每次运行都要输长命令,适合临时测试用,长期用还是建议方法1或2。
小提醒:如果你的课程和评论是分开的爬虫(一个爬课程列表,一个爬评论),那更简单,直接给每个爬虫单独配置Feed或者Pipeline就行,不用加item_type标记。
内容的提问来源于stack exchange,提问作者Luis Ramon Ramirez Rodriguez

