夜雨聆风学习资料网

ARTICLE · 1168098

PDF 表格怎么进 Excel:我造了 259 格标准答案,把 5 条路线逐格比了一遍

PDF 表格怎么进 Excel:我造了 259 格标准答案,把 5 条路线逐格比了一遍

月底对账,我盯着一份 36 行的报销明细 PDF,一行一行敲进 Excel。敲到第 20 行发现金额列整体错了一位,前面全废。

这种活每个月都有,而且没有任何一个环节需要动脑子:PDF 里明明就有表格,只是它不肯让你选中复制。

所以我把手上的招全试了一遍,还造了一份知道标准答案的表格,逐格比对。结果跟我想的不一样。

先给结论

259 个格子,5 条路线,4 种 PDF:

路线
电子版
无框线
扫描件
随手拍
耗时
① PyMuPDF
(免费)
100%0%0%
0%
0.25 秒
② pdfplumber
(免费)
100%0%0%
0%
0.25 秒
③ 文本喂大模型
100%
100%
用不了
用不了
129–182 秒
④ 多模态读图
100%
100%
100%
100%
58–162 秒
⑤ 专用 OCR 模型
61.8%
100%
91.9%
90.3%
16–27 秒

两条免费路线在最标准的电子版上是 0.25 秒满分,最快的 AI 也要 16 秒,最慢的是免费路线的 649 倍。

但换个 PDF,免费路线直接归零:一张表都认不出来。

差别不在工具谁强谁弱,在你手上那份 PDF 属于哪一种。
我的测法:先造一份知道答案的表

横评最怕"看起来还行"。所以我用代码造了一份报销明细表,答案我自己写的:36 行 × 7 列 = 252 格,加 7 个表头,共 259 格。

里面埋了真实 PDF 常有的六个坑:合并单元格表头、跨页且第二页重复表头、金额带 ¥ 和千分位、单元格内换行、空单元格、结尾合计行。

然后把它做成四种形态,也就是四条路线要面对的四份卷子。

四份卷子

电子版:系统导出的那种,有文本层、有框线。 无框线:有文本层,但表格没画线(很多导出工具就这样)。 扫描件:渲染成图片再打包,文本层字符数为 0,轻微倾斜。 随手拍:120dpi、歪 2.6 度、压到 62% 画质,模拟举着手机拍的。

第一步:10 秒判断你手上的是哪种

这是全文最该抄走的一条命令。它只干一件事:数一数 PDF 里有没有文本层。

python -c "import pymupdf,sys;d=pymupdf.open(sys.argv[1]);n=sum(len(p.get_text().strip()) for p in d);print('文本层字符数',n,'->','电子版' if n>50 else '扫描件/拍照件')" 你的.pdf

我的四份卷子跑出来是这样:

报销明细_Q3.pdf        文本层字符数 1732 -> 电子版
报销明细_Q3_扫描件.pdf  文本层字符数 0    -> 扫描件/拍照件

字符数大于 50 就是电子版,意味着文字能被程序直接读出来,不用认图。小于 50 基本等同于图片,所有"按坐标还原"的免费工具当场失效。

这条命令决定你后面走哪条路,比选工具重要得多。

路线 ①②:免费工具的荣光和死穴

两条都是纯规则思路:读 PDF 里文字的坐标和框线位置,把格子还原出来。不联网、不花钱、不调 API。

电子版上,两个都拿了 100%,耗时 0.25 秒。代码也就几行:

import pymupdf
d = pymupdf.open("报销明细_Q3.pdf")
for page in d:
for tb in page.find_tables():
        rows = tb.extract()      # 直接是二维列表

换到无框线那份,find_tables() 返回空列表。pdfplumber 好一点,找出了 2 行,但内容全不对,准确率还是 0%。

扫描件和随手拍更干脆:0.00 秒返回,一行没有。

原因很直白:这两条路线的全部依据是框线和文本坐标。没有框线,它不知道格子在哪;没有文本层,它连字都没有。

免费工具不是不准,是它只认一种 PDF。认不出来的时候它不报错,只是安静地给你一张空表。

这一点最坑:跑完不报错、日志干净、输出 0 行。你要是自己不数一遍行数,会以为"这个 PDF 里没有表格"。

路线 ③④:大模型全能,但你得等

路线 ③ 是把文本层直接喂给通用大模型,让它整理成 CSV。路线 ④ 是把每一页渲染成图,交给多模态模型去读。

两者在无框线那份上都拿了 100%——这正是免费工具归零的地方,也是 AI 真正的价值所在。

路线 ④ 更强:扫描件和随手拍也都是 100%,哪怕图歪了 2.6 度、压到 62% 画质。

代价是时间。路线 ③ 处理一份两页的表要 129 到 182 秒,路线 ④ 是 58 到 162 秒。同样的活,免费工具 0.25 秒。

耗时对比

还有个隐性成本:路线 ③ 一次吃掉 1355 个输入 token,路线 ④ 是 4453 个。单份看都是几分钱的事,但如果你每个月要处理几百份,这个差距会变成账单。

路线 ⑤:专用 OCR 模型,快但会多吐一列

DeepSeek-OCR 这类模型是专门为"读图取字"训的,不走通用对话那套,所以快很多:16 到 27 秒,只有多模态路线的五分之一。

扫描件 91.9%、随手拍 90.3%、无框线 100%。

但在最简单的电子版上,它只有 61.8%,是全场最差。我查了输出,原因是这样的:

表头行:| 基本信息 | 费用信息 | 编号 | 日期 | 费用类别 | 金额(元) | 经办人 | 审批状态 | 备注 |
数据行:| F-2026-001 | 07-03 | 交通差旅 | ¥1,280.00 |  | 张岚 | 已通过 | 高铁往返含市内打车 |

数据行比表头少一列,但在金额后面凭空多了一个空单元格。于是经办人、审批状态、备注三列整体右移一位,36 行全错。

删掉那个空列就是满分。但你拿到手的时候不知道该删哪一列,只会看到"金额后面那一列怎么是空的"。

列错位示意

拿到 AI 输出,先做这三个检查

不管走哪条 AI 路线,这三件事我每次都做,因为它们错起来都不报错:

一、数一数列数。 输出的行是不是和表头一样长?路线 ⑤ 就栽在这里。

二、看金额有没有被劈成两列。¥1,280.00 里的逗号是千分位,CSV 也拿它当分隔符。直接 split(",") 会把一格劈成两格,后面所有列跟着错位。我自己第一版评测脚本就是这么错的,把一个满分结果判成了 61.4%。

三、核对合计行。 把金额列加一遍,跟表尾的合计对得上吗?对不上说明中间有行丢了或者数字抄错。

# 千分位逗号保护:只切列分隔符,不切数字里的逗号
import re
protected = re.sub(r"(?<=\d),(?=\d{3}(?:\D|$))", "\x00", line)
cells = [c.replace("\x00", ",") for c in protected.split(",")]
到底该选哪条

决策流程

按你手上 PDF 的类型往下走:

你的 PDF
选哪条
为什么
有文本层、表格有框线
① 或 ②
0.25 秒满分,别花钱
有文本层、表格没框线
③ 或 ④
免费工具在这里归零
扫描件 / 手机拍照
④ 要准,⑤ 要快
100% vs 90%,162 秒 vs 27 秒
一次几百份、能接受 90%
⑤
速度是 ④ 的五倍

一个提醒:这个表的前提是表格结构规整。我的测试表列宽固定、没有斜线表头、没有嵌套表。如果你手上是那种一格套一格的复杂表,五条路线都得人工复核,别指望全自动。

值不值得折腾

值得,但只值得一次。

免费那两条路线,装好库之后就是一段 10 行的脚本,以后每次跑 0.25 秒。真正的门槛不是代码,是先花 10 秒判断 PDF 类型——这一步省掉了我后面绝大部分的返工。

至于 AI 那三条,我的用法是备着,不常用。只有碰到无框线或者拍照件、而且量不大时才上。几百份的量我会先看看能不能让对方重新导出一份带文本层的电子版,这比任何工具都管用。

点击下方蓝色链接,领取本文资料包

四份测试 PDF、259 格标准答案、五条路线的可运行脚本、逐格比对的评测脚本,全在里面,换成你的 PDF 就能跑。

点此领取:PDF 表格提取实测包

相关学习资料