You need to enable JavaScript to run this app. Scrapy使用FilesPipeline下载需认证的CSV文件无扩展名且报空字节错误
优惠活动
大模型
产品
解决方案
定价
更多

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方法自定义命名规则:

  1. 在项目的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}'
  1. 修改settings.py中的管道配置,替换默认的FilesPipeline:
ITEM_PIPELINES = {'你的项目名.pipelines.CustomCsvPipeline': 1}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 08:15:03