read_html 返回空列表主因是仅解析原始HTML中的规范<table>标签,若表格由JS渲染、藏于注释或display:none中则无法获取;需先查源码确认存在性。

read_html 为什么经常返回空列表?
因为 read_html 默认只解析 <table> 标签,且要求 HTML 结构“相对规范”:比如不能嵌套在 <div style="display:none"> 里,不能是 JS 渲染后才插入的表格。遇到空列表,先用浏览器「查看页面源代码」确认 <table> 标签是否真实存在于原始 HTML 中——如果源码里没有,read_html 就无能为力。
常见干扰项包括:
- 表格由 Vue/React 渲染,源码中只有占位
<div id="app"></div> - 表格被包裹在
<script type="text/html">或注释块里 - 使用了
colspan/rowspan过度复杂的合并单元格(部分版本 pandas 解析失败)
如何指定要提取的第几个表格?
read_html 总是返回 list,哪怕页面只有一个 <table>。别直接取 df = pd.read_html(url)[0] 就完事——容易错拿广告栏或隐藏统计表。
稳妥做法:
立即学习“Python免费学习笔记(深入)”;
- 先运行
tables = pd.read_html(url),然后print(len(tables))看总数 - 逐个检查:例如
tables[2].head(),观察列名、数据特征是否匹配目标 - 用
match参数缩小范围:pd.read_html(url, match="订单编号|商品名称"),它会正则匹配表格内任意文本(不是 table 标签名)
注意:match 对大小写敏感,中文需确保编码一致;若匹配到多个表格,仍返回列表,只是长度可能变短。
表格有合并标题行或无表头,怎么处理?
默认情况下,read_html 把第一行当列名(header=0),但很多网页表格首行是“2024年销售汇总”这类大标题,真正字段名在第二或第三行。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
关键参数组合:
-
header=[0,1]:把前两行合并为 MultiIndex 列名(适合分级表头) -
skiprows=1:跳过首行再找 header,配合header=0使用 -
header=None:强制不设列名,返回纯数字列索引,后续用df.columns = ["A","B"]手动赋值 -
encoding="gb18030":遇到中文乱码时必加,尤其国内政府网站常用 GBK 系列编码
示例:pd.read_html(url, encoding="gb18030", skiprows=1, header=0) —— 适用于首行为标题、第二行为字段名的常见政务表格。
为什么 DataFrame 里全是 NaN 或类型错误?
这是 read_html 的隐式类型推断惹的祸。它会自动把看起来像数字的字符串转成 float64,结果把带单位的“12.5万元”变成 NaN,或把“2024-03”识别成日期后填进不存在的日期列。
解决方式:
- 加
dtype=str强制全转字符串:pd.read_html(url, dtype=str),后续再按需用.str.replace清洗 - 对特定列控制类型:
dtype={"成交价": str, "数量": "int64"} - 禁用自动解析:
converters={"成交价": lambda x: x},绕过内置转换逻辑
另外,含大量空单元格的表格,na_values 参数可扩展识别为缺失值的字符串,比如 na_values=["--", "暂无", "-"]。
真正难的不是调用 read_html,而是判断它“为什么没拿到想要的那张表”——得习惯先看源码、再试参数、最后查 pandas 版本兼容性。0.25.3 之前对 rowspan 支持极差,1.5+ 又改了 match 的默认行为,这些细节不踩一遍坑很难记住。

















