Scrapy使用FilesPipeline下载需认证的CSV文件无扩展名且报空字节错误
问题根因
你遇到的是两个独立问题:
1. CSV解析报错的核心原因
你下载的文件本身内容没有损坏,只是源站返回的CSV采用了UTF-16 LE编码,你在vim中看到的^@就是UTF-16编码下ASCII字符附带的空字节,Python自带的csv模块默认用UTF-8编码读取文件,就会抛出_csv.Error: line contains NULL byte的错误。
Notepad++会自动识别文件编码,你手动转存为UTF-8后空字节被移除,自然可以正常读取。
2. 文件无扩展名的原因
Scrapy默认的FilesPipeline采用文件内容的SHA1哈希作为保存文件名,不会自动保留原文件的扩展名,和源站返回的内容无关。
解决方案
编码问题快速解决
不需要手动转存文件,读取时直接指定编码即可正常解析:
import csv with open('下载的哈希文件名', 'r', encoding='utf-16') as f: reader = csv.reader(f, delimiter=';') for row in reader: print(row)
如果需要直接下载得到UTF-8编码的文件,可以自定义Pipeline在下载后自动转码。
自动保存为带.csv后缀的文件
需要继承FilesPipeline重写file_path方法自定义命名规则:
- 在项目的
pipelines.py中新增自定义管道:
from scrapy.pipelines.files import FilesPipeline class CustomCsvPipeline(FilesPipeline): def file_path(self, request, response=None, info=None, item=None): # 可根据需求自定义文件名,这里示例固定为export.csv,也可以加时间戳、唯一标识避免覆盖 return 'full/export.csv' # 如果需要从响应头提取源站返回的文件名,可以用如下逻辑: # if response and 'Content-Disposition' in response.headers: # disp = response.headers['Content-Disposition'].decode() # filename = disp.split('filename=')[1].strip('"') # return f'full/{filename}'
- 修改
settings.py中的管道配置,替换默认的FilesPipeline:
ITEM_PIPELINES = {'你的项目名.pipelines.CustomCsvPipeline': 1}
内容的提问来源于stack exchange,提问作者kekw
相关产品推荐
相关产品推荐

