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
</li></ul><p>class Utf8CsvItemExporter(CsvItemExporter):
def <strong>init</strong>(self, *args, *<em>kwargs):
kwargs.setdefault('encoding', 'utf-8')
super().<strong>init</strong>(</em>args, **kwargs)</p><p>class Utf8FileFeedStorage(FileFeedStorage):
def open(self, spider):
return super().open(spider)</p>- 在
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 必须指向类的完整导入路径。
Claw Code Suite (Python-Only Edition)
仅使用 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。
Scrapy 的 CSV 导出链里有三层脱节:ItemExporter 不控制文件打开、FeedStorage 不传 encoding、csv.writer 不处理编码——所以必须从中间层切入,缺一不可。
FEED_STORAGE_BACKEND,换用支持编码的自定义存储类:
- 在项目根目录新建
myproject/feedexport.py,内容如下:from scrapy.exporters import CsvItemExporter from scrapy.extensions.feedexport import FileFeedStorage </li></ul><p>class Utf8CsvItemExporter(CsvItemExporter): def <strong>init</strong>(self, *args, *<em>kwargs): kwargs.setdefault('encoding', 'utf-8') super().<strong>init</strong>(</em>args, **kwargs)</p><p>class Utf8FileFeedStorage(FileFeedStorage): def open(self, spider): return super().open(spider)</p>- 在
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必须指向类的完整导入路径。
Claw Code Suite (Python-Only Edition)下载仅使用 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。
Scrapy 的 CSV 导出链里有三层脱节:ItemExporter 不控制文件打开、FeedStorage 不传 encoding、csv.writer 不处理编码——所以必须从中间层切入,缺一不可。
- 在

















