scrapy导出csv中文乱码的根本原因是csv模块不支持直接指定编码,且filefeedstorage硬编码文本模式无encoding参数;需自定义utf8csvitemexporter和utf8filefeedstorage类并配置feed_exporters与feed_storages。

Scrapy导出CSV时中文乱码的根本原因
Scrapy默认用 csv 模块导出,而该模块不支持直接指定编码;它底层写入的是字节流,但 FeedExporter 在打开文件时没传 encoding 参数,导致在 Windows 上常默认用 cp1252,Linux/macOS 虽多为 UTF-8,但显式声明仍有必要。这不是文件保存问题,是 Scrapy 的 FileFeedStorage 类硬编码了文本模式无编码参数。
修改 settings.py 强制 UTF-8 输出
最直接有效的方式是覆盖默认的 FEED_STORAGE_BACKEND,换用支持编码的自定义存储类:
- 在项目根目录新建
myproject/feedexport.py,内容如下:
from scrapy.exporters import CsvItemExporter
from scrapy.extensions.feedexport import FileFeedStorage
FEED_STORAGE_BACKEND,换用支持编码的自定义存储类:
- 在项目根目录新建
myproject/feedexport.py,内容如下:from scrapy.exporters import CsvItemExporter from scrapy.extensions.feedexport import FileFeedStorage
class Utf8CsvItemExporter(CsvItemExporter): def init(self, *args, *kwargs): kwargs.setdefault('encoding', 'utf-8') super().init(args, **kwargs)
class Utf8FileFeedStorage(FileFeedStorage): def open(self, spider): return super().open(spider)
- 在
settings.py中添加:FEED_EXPORTERS = { 'csv': 'myproject.feedexport.Utf8CsvItemExporter', } FEED_STORAGES = { 'file': 'myproject.feedexport.Utf8FileFeedStorage', } FEEDS = { 'output.csv': { 'format': 'csv', 'overwrite': True, }, }
注意:Scrapy 2.6+ 推荐用 FEEDS 替代旧的 FEED_URI,且必须确保路径是字符串(不能是 Path 对象);FEED_EXPORTERS 必须指向类的完整导入路径。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
绕过自定义类的临时方案(仅限调试)
如果不想改代码结构,可临时用 scrapy crawl myspider -o output.csv --set FEED_EXPORT_ENCODING=utf-8 启动。但该参数只影响部分导出器(如 JSONLines),对 CSV **无效**——这是常见误区。Scrapy 官方文档明确说明 FEED_EXPORT_ENCODING 对 CSV 不生效,因为 csv.writer 本身不接受 encoding 参数。
验证输出是否真为 UTF-8
不要只靠 Excel 打开看,Excel 会自动猜测编码并可能错误转码:
- 用命令行检查:
file -i output.csv(Linux/macOS)或 chcp + 记事本另存为时查看编码下拉框
- 更可靠的是用 Python 读取并检查:
with open('output.csv', 'rb') as f:
raw = f.read(100)
print(raw[:20]) # 看是否有 BOM(\xef\xbb\xbf)或纯 UTF-8 字节
若含 BOM,说明写了 UTF-8-SIG;不需要 BOM 的话,在自定义 Utf8CsvItemExporter 的 __init__ 中加 kwargs.setdefault('include_headers_line', True) 即可,BOM 是 open(..., encoding='utf-8-sig') 写入的副作用,而我们用的是 encoding='utf-8',不会带 BOM。
- 用命令行检查:
file -i output.csv(Linux/macOS)或chcp+ 记事本另存为时查看编码下拉框 - 更可靠的是用 Python 读取并检查:
with open('output.csv', 'rb') as f: raw = f.read(100) print(raw[:20]) # 看是否有 BOM(\xef\xbb\xbf)或纯 UTF-8 字节若含 BOM,说明写了 UTF-8-SIG;不需要 BOM 的话,在自定义Utf8CsvItemExporter的__init__中加kwargs.setdefault('include_headers_line', True)即可,BOM 是open(..., encoding='utf-8-sig')写入的副作用,而我们用的是encoding='utf-8',不会带 BOM。
Scrapy 的 CSV 导出链里有三层脱节:ItemExporter 不控制文件打开、FeedStorage 不传 encoding、csv.writer 不处理编码——所以必须从中间层切入,缺一不可。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










