怎样正确爬取被 HTML 注释包裹的 Pandas 表格数据

作者:袖梨 2026-07-02

Pandas 的 read_html() 无法解析被 <!-- --> 注释标签包裹的 HTML 表格,导致第二张表返回空 DataFrame;需先清除注释再解析。

pandas 的 `read_html()` 无法解析被 `` 注释标签包裹的 html 表格,导致第二张表返回空 dataframe;需先清除注释再解析。

在使用 pandas.read_html() 爬取网页表格时,一个常见却容易被忽略的问题是:目标表格可能被 HTML 注释符(<!-- 和 -->)包裹。这类内容虽存在于原始 HTML 文本中,但标准 HTML 解析器(如 BeautifulSoup)默认跳过注释节点,read_html() 内部使用的解析器同样如此——因此即使 soup.find_all() 找不到该表,read_html() 直接传入含注释的字符串也会因结构不可见而失败。

上述代码中,stats_keeper 表实际位于注释块内(可查看页面源码验证),所以 soup.find_all('table', {'id': 'stats_keeper'}) 可能返回空列表或索引越界,而后续 pd.read_html(str(table2)) 则因传入的字符串仍含未处理的注释语法,导致解析失败并返回空 DataFrame。

✅ 正确做法是:绕过 BeautifulSoup,直接预处理原始响应文本,移除所有 HTML 注释标记,再交由 pd.read_html() 统一解析。推荐使用 StringIO 将清理后的字符串转为类文件对象,提升兼容性:

from io import StringIOimport pandas as pdimport requestsurl = "https://fbref.com/en/comps/9/keepers/Premier-League-Stats"response = requests.get(url)# 清理注释:简单替换(适用于无嵌套注释的场景)cleaned_html = response.text.replace('<!--', '').replace('-->', '')# 使用 StringIO 包装,确保 read_html 能正确读取html_io = StringIO(cleaned_html)# 一次性解析指定 ID 的表格(更健壮,避免索引错误)df1 = pd.read_html(html_io, attrs={'id': 'stats_squads_keeper_for'}, flavor='bs4')[0]html_io.seek(0)  # 重置指针位置df2 = pd.read_html(html_io, attrs={'id': 'stats_keeper'}, flavor='bs4')[0]print("第一张表(球队门将统计)形状:", df1.shape)print("第二张表(球员门将统计)形状:", df2.shape)

⚠️ 注意事项:

立即学习“前端免费学习笔记(深入)”;

  • replace('<!--', '').replace('-->', '') 是轻量级方案,适用于注释不嵌套、无复杂结构的页面(如 fbref);若页面含多层嵌套注释,建议用正则 re.sub(r'<!--.*?-->', '', text, flags=re.DOTALL) 更安全;
  • 每次调用 pd.read_html() 前需重置 StringIO 指针(seek(0)),否则第二次读取会从末尾开始,返回空结果;
  • 显式指定 flavor='bs4' 可提升解析稳定性,尤其当环境中有多个 HTML 解析器时;
  • 若仍报错,可先保存 cleaned_html 到本地文件,手动检查目标 <table id="stats_keeper"> 是否真实存在且结构完整。

总结:HTML 注释不是“隐藏”,而是“被解析器主动忽略”。与其依赖 DOM 树查找,不如前置清洗原始 HTML 文本——这是爬取动态渲染或注释包裹表格最可靠、最简洁的实践路径。

相关文章

精彩推荐