You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3使用cgi.parse_header下载特殊文件名文件时报错如何解决

问题根因

你的报错和文件名里的连字符、空格没有关系,核心原因是这两个站点的响应头没有返回Content-Disposition字段,你直接读取该字段得到的是None值,传入cgi.parse_header时触发了类型错误。

修复方案

先判断响应头是否携带Content-Disposition,如果没有就自定义文件名规则,同时添加浏览器请求头避免被站点反爬拦截,最后对拿到的文件名做清洗处理特殊字符即可,以下是完整可运行代码:

from urllib.request import urlopen, Request, urlretrieve
import cgi
import os
from urllib.parse import urlparse

# 存储路径
save_path = '/home/edmint/2results/holdingPen/'
# 自动创建路径避免不存在报错
os.makedirs(save_path, exist_ok=True)

# 可替换为你要下载的任意地址
url = "https://www.vaneck.com/etf/equity/smog/holdings/download/xlsx/"
# url = "https://www.globalxetfs.com/funds/driv/?download_full_holdings=true"

# 模拟Chrome浏览器请求头,避免被站点反爬拦截
headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
req = Request(url, headers=headers)
remotefile = urlopen(req)

# 安全获取Content-Disposition头,不存在则返回None
content_disposition = remotefile.info().get('Content-Disposition', None)

filename = ""
if content_disposition:
    value, params = cgi.parse_header(content_disposition)
    filename = params.get("filename", "")

# 未从响应头拿到文件名则从URL生成默认名
if not filename:
    parsed_url = urlparse(url)
    base_name = os.path.basename(parsed_url.path) or "download_holdings"
    # 可根据站点类型自行调整默认后缀
    filename = base_name if '.' in base_name else f"{base_name}.xlsx"

# 清洗文件名:移除首尾空格、替换Linux文件系统不支持的非法字符
filename = filename.strip().replace('/', '_').replace('\\', '_')
# 安全拼接保存路径,适配不同操作系统规则
full_save_path = os.path.join(save_path, filename)

# 执行下载
urlretrieve(url, full_save_path)
print(f"文件已成功保存到:{full_save_path}")

代码说明

  • 新增浏览器UA模拟正常访问,避开大部分站点的爬虫拦截规则
  • 对Content-Disposition做了存在性校验,完全避免读取空值触发的类型错误
  • 无响应头文件名时自动生成备用名称,下载流程不会中断
  • 自动清洗文件名首尾空格、特殊字符,带连字符、末尾空格的文件名都可以正常保存
  • 用系统自带的路径拼接方法,避免手动拼接路径的语法错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:42:02