使用pandas读取网站下载的XLS文件报XLRDError如何解决
问题根因
你遇到的XLRDError: Unsupported format, or corrupt file错误,本质是下载的文件并非标准二进制XLS格式,而是微软XML Spreadsheet 2003格式的纯文本文件:
- 开头的
\xef\xbb\xbf是重复的UTF-8 BOM头,后续的<?是XML声明的起始标识,xlrd仅支持老式二进制XLS格式,无法识别该类XML结构的伪XLS文件 - Excel能正常打开是因为它原生兼容XML Spreadsheet格式,弹出扩展名不匹配警告也正是因为文件实际格式和后缀名不符
解决方案1:纯Python解析(无需额外工具依赖)
该方案直接解析XML格式的内容,不需要调用外部程序,跨平台可用。
先安装依赖:
pip install requests pandas lxml
代码示例:
import requests import pandas as pd from io import BytesIO # 下载文件内容 download_url = "https://www.blackrock.com/uk/individual/products/291392/fund/1527484370694.ajax?fileType=xls&fileName=iShares-MSCI-World-SRI-UCITS-ETF-USD-Dist_fund&dataType=fund" headers = { # 模拟浏览器请求,避免被官网拦截 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } resp = requests.get(download_url, headers=headers) resp.raise_for_status() # 解析XML Spreadsheet格式内容,指定命名空间匹配表格结构 ns = {"ss": "urn:schemas-microsoft-com:office:spreadsheet"} tree = pd.read_xml(BytesIO(resp.content), xpath="//ss:Worksheet[@ss:Name='Holdings']/ss:Table/ss:Row", namespaces=ns) # 处理表头和空行:跳过前3行说明内容,重置列名 df = tree[3:].reset_index(drop=True) df.columns = tree.iloc[2].tolist() # 清理空列空值 df = df.dropna(axis=1, how="all")
解决方案2:调用ssconvert自动转格式(格式兼容更好)
如果需要更稳定的格式兼容,可以使用开源工具ssconvert(属于Gnumeric办公套件的组件)自动将XML Spreadsheet转成标准xlsx格式,全程不需要手动操作:
- 先安装Gnumeric:
- Windows:搜索下载Gnumeric官方安装包,安装后把安装路径加入系统环境变量
- macOS:执行命令
brew install gnumeric完成安装 - Linux:执行命令
sudo apt install gnumeric完成安装
- Python代码示例:
import requests import os import pandas as pd import subprocess download_url = "https://www.blackrock.com/uk/individual/products/291392/fund/1527484370694.ajax?fileType=xls&fileName=iShares-MSCI-World-SRI-UCITS-ETF-USD-Dist_fund&dataType=fund" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } # 下载原始文件存为临时文件 with open("temp_holdings.xls", "wb") as f: f.write(requests.get(download_url, headers=headers).content) # 调用ssconvert转成标准xlsx subprocess.run(["ssconvert", "temp_holdings.xls", "temp_holdings.xlsx"], check=True, capture_output=True) # 读取转换后的xlsx df = pd.read_excel("temp_holdings.xlsx", sheet_name="Holdings", skiprows=3) # 清理临时文件 os.remove("temp_holdings.xls") os.remove("temp_holdings.xlsx")
注意事项
- 贝莱德官网有反爬机制,请求时需要携带
User-Agent头,否则可能返回403错误 - 两种方案都不需要手动操作Excel,全程自动化完成
内容的提问来源于stack exchange,提问作者Christoffer Madsen
相关产品推荐
相关产品推荐

