有回在内网系统里,领导扔过来一句话:“把这页数据导出来,我要做报表。” 你打开那个古董级的内部系统,扫了一圈——没导出按钮,右键菜单被锁,甚至网络请求都看不出个所以然。
你猜怎么着?这事儿我干过不止一回。
说白了,这种“只能看不能动”的表格,在内网系统里遍地都是。要么是安全策略不让导,要么是开发的时候压根没做导出功能。
这篇文章,咱们就把这件事掰开揉碎讲清楚:用Python怎么自动识别并导出网页表格(不管是table还是div),最终落成Excel。 顺便看看市面上有没有能直接拿来用的开源方案。
一个“内网专用”工具的核心诉求
先给这个场景下个定义:目标系统在内网,不连外网,不能用云端API。我们需要一个纯本地运行、开箱即用、能自动识别表格的工具。
踩坑警告:别一上来就想着用OCR去识别网页截图。网页本身就有DOM结构,直接从HTML里解析表格,精度比OCR高一个量级,而且速度更快。
场景A:标准的 <table> 表格
这是最理想的状况。网页里的表格如果用了标准的 <table>、<tr>、<td> 标签,那解析起来就是降维打击。
为什么 pandas.read_html() 经常翻车
很多人第一反应是 pandas.read_html(),这玩意儿对付简单表格确实快,但有个坑——它处理不了 rowspan 和 colspan 。
但凡表格里有个合并单元格,read_html() 返回的DataFrame大概率是错位的。
import pandas as pd
# 看起来很美好,遇到合并单元格就露馅
tables = pd.read_html("https://internal-system/report")
print(tables[0])
解决方案:tabulate-html 专治合并单元格
有个新出的库叫 tabulate-html,官方定位就是“比 pandas.read_html 更擅长处理复杂表格”。
它用了一个二维矩阵映射的方式,把 rowspan 和 colspan 精准展开,实测效果吊打一众轻量级解析器。
from tabulate_html import parse_html_tables
import pandas as pd
html_content = """
<table>
<tr><th rowspan="2">姓名</th><th colspan="2">联系方式</th></tr>
<tr><th>电话</th><th>邮箱</th></tr>
<tr><td>张三</td><td>138xxxx</td><td>zhangsan@xx.com</td></tr>
</table>
"""
# 指定前两行是表头
data = parse_html_tables(html_content, header_rows=[0, 1])
df = pd.DataFrame(data)
df.to_excel("output.xlsx", index=False)
运行结果:rowspan 和 colspan 被自动展开,表头合并成 姓名_联系方式_电话 这种层级结构。
这玩意儿特别适合那种表头有三四层、各种合并单元格的复杂财务报表。
场景B:用 <div> 拼出来的假表格
这是内网系统的重灾区。前端为了样式统一,用一堆 <div> 拼出表格布局,没一个 <table> 标签。
这时候上面的方法全废。
方案:puppeteer-table-parser + 无头浏览器
puppeteer-table-parser 是一个专门为 Puppeteer 设计的表格解析库,核心思路是:通过CSS选择器定位行和列,按列名提取数据。
import { tableParser } from 'puppeteer-table-parser';
await tableParser(page, {
selector: '.my-table-class', // 表格容器
allowedColNames: {
'工号': 'employee_id',
'姓名': 'name',
'部门': 'department'
},
headerRowsSelector: '.header-row', // 自定义表头行选择器
bodyRowsSelector: '.data-row', // 数据行选择器
rowValuesAsArray: false
});
输出:直接生成CSV或JS对象数组,拿去做Excel导出就完事了。
这个方案的核心价值在于:它可以处理不合规的HTML结构,哪怕表格长得再歪,只要你能用选择器圈出行列,它就能给你吐数据。
场景C:纯静态页面 + 简单表格
如果你遇到的是那种没有花里胡哨JavaScript、结构清晰的静态HTML页面,那杀鸡不用牛刀。
html-table-to-markdown 这个库走的是 BeautifulSoup 路线,专治各种静态页面表格。
from simple_table_parser import parse_tables_to_markdown
# 直接传URL,自动识别所有表格
markdown_content = parse_tables_to_markdown(
"http://internal-system/report",
"output.md"
)
然后把Markdown转Excel?其实它内部用的是 pandas + tabulate,你要改源码把输出改成Excel也不难。
有没有现成的开源“通用导出工具”?
这是个好问题。我认真扒了一圈,结论是:没有一款能通吃所有内网表格的“万能软件”。
但有两条路值得关注:
1. excalibur —— 专攻PDF表格提取
如果你能把网页先打印成PDF,那 excalibur 是个好东西。它本质上是 Camelot 的Web界面版,支持通过画框选的方式提取表格。
pip install excalibur-py
excalibur initdb
excalibur webserver
# 打开 localhost:5000
操作方式:上传PDF → 在页面上框选表格区域 → 选择 Lattice(有线表格)或 Stream(无线表格)→ 导出CSV/Excel。
适用场景:PDF表格结构规范,且用户愿意手动框选。对于内网系统,先把网页另存为PDF再处理,也算一种可行的“迂回战术”。
2. docentra —— AI加持的本地表格工具
这是个新项目,定位是“智能一体化办公工作台”,可以本地运行、导入导出Excel、集成AI智能体。
它的核心能力包括:Excel导入导出、公式计算、筛选排序、AI辅助编辑。目前主要定位是桌面端表格工具,并非专门做网页表格解析。
实战方案选型对照表
| 网页表格特征 | 推荐方案 | 原理 | 复杂度 |
|---|---|---|---|
标准 <table> + 无合并单元格 | pandas.read_html() | 直接解析HTML | 低 |
<table> + 复杂合并单元格 | tabulate-html | 二维矩阵映射展开合并 | 中 |
<div> 仿表格 | puppeteer-table-parser + Puppeteer | 无头浏览器 + CSS选择器 | 高 |
| 静态页面 + 基础表格 | html-table-to-markdown | BeautifulSoup解析 | 低 |
| 可转PDF的页面 | excalibur (Camelot) | 手动框选表格区域 | 中 |
我的建议:别追“万能”,要追“够用”
说实话,一个工具通吃所有内网表格这事儿,本身就是个伪命题。内网系统的HTML质量参差不齐,有的连基本语义都没有。
我的实战策略是:
- 先F12看DOM结构——判断是
table还是div,决定技术路线。 - 优先选
tabulate-html——只要页面有<table>标签,这玩意儿的兼容性比read_html强太多。 - 遇到div表格直接上Puppeteer方案——别在BeautifulSoup上浪费时间调试选择器。
- 实在不行就打印PDF用
excalibur——手动框选虽然麻烦,但能保证数据准确。
有回我就遇到过一张报表,表格用 <div> 渲染,但每个数据行都藏在一个 data-row-id 属性里。用 puppeteer-table-parser 配合自定义 rowValidator,十分钟搞定。
你要做的,不是找一个“万能软件”,而是根据页面特征快速选型。上面这几套方案组合起来,基本能覆盖内网系统里95%的表格导出需求。


