一份 11 页、带水印的 PDF 文档,要提取成结构化的 Markdown 并逐项核对准确。最后靠的不是"让 AI 读一遍",而是一套可证明的坐标法——文字靠取、水印靠认、表格归属靠坐标算、最终靠人眼验。
写作角色本文以第一人称技术复盘的口吻展开——重方法、轻煽情,把每一步的依据和边界都摊开讲。
01
PART
任务:一份"很难缠"的 PDF
拿到手的是一份带水印的文档,11 页,发布与实施日期清晰。
表面看没什么特别。细看却有两道坎。
一是水印。每页两处旋转的灰色文字——"2025年05月06日 09点10分",斜斜压在正文上。
二是表格复杂。表 2"产品主要成分分析保证值"有 13 个产品分型,从 Ⅰ 型排到 ⅩⅢ 型。多个型还分 a/b/c 子列,合并单元格密集,数值里还夹着科学计数法。
目标很明确:整理成一份干净的 Markdown,并且逐项核对准确——每个数值、每项检测方法、每行到底属于哪个型,都得说得清出处。
02
PART
为什么文本可以"取",不用"认"
不少人以为 AI 处理 PDF 是"用眼睛看、用脑子认"。其实不是。
这份 PDF 是文字版,不是扫描件。文件里每个字符都是一个独立对象,自带内容和坐标。提取文字就像从数据库里读记录,不存在"认错字形"的问题。
这一步性质完全不同:扫描件是"看"出来的,文字版是"取"出来的。
我跑了两条独立管线各抽一遍全文:
• `pdftotext`:命令行工具,抽出 21,001 个字符
• PyMuPDF:Python 库,按 span(文本片段)逐个提取
两边交叉比对,结果一致,无乱码。先排除了"工具抽坏了"的可能。
水印也一样。它本质上就是文字版里的普通文字,只不过被旋转过。我把每个字符片段按顺序拼接,凡是拼出来恰好等于"公开 2025年05月06日 09点10分"的,就判定为水印、剔除。每页两处,11 页共 22 处,全部清掉。
认水印靠的是文本特征,不是肉眼涂改。
03
PART
最难的一关:这行到底属于哪个型
文本提取是体力活。真正的难点在表 2 的归属判断。
问题出在"产品分型"列。它是纵向合并单元格:
0.5%水产动物复合预混合饲料 Ⅰ型 戊糖片球菌,cfu/g ≥ 1.0×10⁵ Q/××× ... 乳酸肠球菌,cfu/g ≥ 1.0×10⁵ Q/××× ... 屎肠球菌,cfu/g ≥ 2.0×10⁵ Q/××× ... ...
"Ⅰ型"三个字只在 PDF 里出现一次,却管着下面好几行。PDF 数据里没有"这行属于哪格"的现成信息。一行到底归 Ⅰ 型还是 Ⅱ 型,只能推断。
最初我按"行顺序"猜,错了 6 处。
原因很微妙。合并单元格的标题文字是垂直居中的,它出现在整个分区的正中间,而不是分区开头。按行数顺序,会把"下一个标题之前的所有行"全归给上一格——结果把两个型的分界看反了。
后来改用坐标法。PyMuPDF 能给每个文字片段精确的 x(横向)和 y(纵向)坐标。归属判断变成一道几何题:
找到每个"产品分型"标题的 y 坐标;
标题垂直居中于自己管辖的行区段——比如 Ⅱ 型标题在 y=328.8,而它下面的行范围是 y≈288 到 y≈384,标题恰好落在正中;
每一行按 y 坐标就近归入所在区段。
这一改,6 处归属全部翻案:
| Ⅱ 型 | ||
| Ⅳ 型 | ||
| Ⅸ 型 | ||
| Ⅹ 型 | ||
| ⅩⅠ 型 | ||
| = 2 |
酵母硒那一格最戏剧性:数值刚好压在水印下面,肉眼和行序法都看不出来。坐标定位后确认它就是"2"。
它一直在那里,只是没人知道去哪里找它。
04
PART
顺带发现:原文自己也有 5 处笔误
核对到后面,有些"错误"不是我的,是原文 PDF 自己写错了:
表 2 的"ⅩⅡ 型"表头,原文误写成"Ⅵ型-a Ⅵ型-b"(数字抄错);
正文说"具体指标见表2",指标实际在表 3(引用编号错);
"25-羟基维生素3"缺了个"D"(应为维生素 D3);
贮存段"……混贮保质期"中间没有标点;
某条检测方法写成"农业部2483号公告-5-2016",格式罕见,疑似笔误(存疑项)。
这件事提醒我一点:文档审核的对象,不一定是"标准答案"。程序能证明"数据从 PDF 里来了",但证明不了"PDF 自己没写错"。
05
PART
验证链:哪些能证明,哪些只能人眼
核对完有人问:你凭什么确定数据准确?
我的回答分三层,每一层的可信度不一样。
第一层,文本抽取——可证明。文字版 PDF 直接取出,双管线交叉一致,不存在认错。
第二层,数值比对——可证明。标准编号(GB/GB/T/NY/T/SN/T 等 40+ 项)双向比对零差异;每个数值都能在原 PDF 的坐标位置找到对应字符。
第三层,表格归属——推断。按"标题垂直居中"假设划分,结果自洽且置信度高,但不是数学证明。如果有朝一日拿到单元格边界的原始数据,个别归属可能还有争议。
所以最终验收我交给了一件事:渲染成页面图片,人眼逐页目检。
程序负责"取准",人负责"看懂"。这最后一公里,恰恰是我替不了的那一步。
06
PART
把方法沉淀下来
这次经历提炼成一条可复用的核对流程:
先判断文件类型:文字版直接取,扫描版才上 OCR(且 OCR 必须抽查);
双管线交叉:两个工具独立提取,结果一致才可信;
有水印先认水印:按文本特征精确剔除,不用涂改;
表格归属靠坐标:合并单元格的标题垂直居中,用 y 坐标分区,别按行序猜;
区分"证明"和"推断":告诉别人哪些是铁证、哪些需要人工复核;
最后必须人眼验收:渲染成图,逐页看。
机器负责它擅长的,人守住自己那关。这是我在这次任务里学到的最大一课。
夜雨聆风