扫描件 PDF:先判断有没有文字层,再修

十秒分辨扫描件还是文本件,工具为什么用 PDF_NO_TEXT_LAYER 直接拒绝,怎么在不把页面送出去的前提下做 OCR,以及识别错误如何变成检索错误。

· 8 分钟阅读

扫描件 PDF 是页面的一张图,而文本提取器只能返回页面上真实存在的字符,问题就出在这里:文件看起来是文档,打开也像文档,里面却一个字都没有。下面讲怎么用十秒确认这一点、怎么在不把页面送出去的前提下做识别,以及识别错误之后对检索造成的影响。

十秒判断扫描件还是文本件

第一种办法不需要任何额外工具。用你手上的阅读器打开 PDF,在页面中间挑一段普通正文,用鼠标去选。文本件会高亮出文字,也能复制;扫描件什么都不会高亮,或者一拖就拽出一个整页大小的框,像抓住了一张图片。

第二种办法是工具自己的回答。把文件拖进去看状态:扫描件会被拒绝并报出 PDF_NO_TEXT_LAYER,提示里写明未检测到文字层。这个错误码是专用的——它和加密文件的 PDF_ENCRYPTED 不同,也和超大文件的 FILE_TOO_LARGE 不同。

你看到的 说明什么 接下来怎么做
任何阅读器里都能选中并复制文字 文件有真正的文字层 直接导入,下面都不用看
选不中,但页面清晰、字型规整 电子生成的扫描件,多半是从排版稿渲染的 做 OCR,导入识别结果
页面是纸的照片,有倾斜和阴影 相机或平板扫描仪拍的 做 OCR,导入前先核对
导入报 PDF_NO_TEXT_LAYER 解析器在整份文件里读到零个字符 先 OCR,再导文本
导入报 PDF_ENCRYPTED 设置了密码或所有者限制 在生成它的工具里去掉保护,再导入解密后的副本

还有一种混合文件:报告正文是文字层,附件是扫描页。解析器会把它能取的取出来,结果就是索引里只有正文,附件是空的。在断定某条款不存在之前,这一点值得先确认。

工具为什么直接拒绝,而不是塞个空壳

技术上当然可以接受扫描件、然后索引一个占位符,或者只把文件名和页数写进去。这样做的结果是得到一个看起来健康、实际什么都答不出来的索引。一个明确的错误比一个沉默的空文档有用,所以解析器抛出错误码并把原因写在提示里。

隐私上也有一条理由,让这个决定保持显式。扫描件里敏感材料的比例偏高:签了字的合同、证件页、体检表、银行流水。恰恰是这类材料,先上传的工作流代价最大;也恰恰是这类材料,一个挡住导入的错误帮了你一把。

在不把页面送出去的前提下做 OCR

原则很简单:识别应该发生在图像已经在的地方。三种安排里只有一种是远程的。

  1. 在浏览器里识别。 一部分扫描软件和文档工具自带在页面内运行的识别引擎,不往外发任何东西。
  2. 在你自己的电脑上识别。 桌面版 OCR 程序,或者装在机器上的命令行识别工具,用你自己的处理器处理页面,输出一个文本文件,再导进来。
  3. 在别人的电脑上识别。 云端 OCR 服务接收图像并返回文字。页面图像在进去的路上就离开了你的设备,之后怎么留存由服务方的规则决定。

只有前两种让材料留在本地。用第三种的话,如实地说,这个扫描件已经披露给了另一个主体;后续的导入虽然发生在本地,但整个故事已经不完整了。凡是有签署、有账号、有保密条款的内容,请走前两条路,接受多花的那几分钟。

具体该用哪个本地识别工具,本文给不了承诺,因为这个领域的工具变化很快,我们也没有逐一测试过。选择时优先考虑安装后可以完全离线运行的,并且用你验证本站的同一个办法去验证它:断网看它还能不能干活。

把识别出来的文本导回来

拿到文本之后,导入路径和任何纯文本文件一样,这一步的几个选择会在后面省事。

  • 保留页码标记。 识别工具如果能在每页开头插入页码或分页标记,就留着。带页码的文本块元信息能让引用指回你可以用眼睛核对的那一页。
  • 导文本或 Markdown,别导重新包好的 PDF。 识别生成的可搜索 PDF 只多了一个容器,没有增加可检索内容,还要占用单文件和总量额度。
  • 有标题就把标题恢复出来。 识别成的一行标题,如果不标成 Markdown 标题,就只是普通句子。恢复标题层级等于给切分器真实边界,差别是干净的一块和从上一节中间开始的一块。
  • 按文档分,不要按文件夹分。 限额针对单个文件和整个库,所以一份 60 页扫描件导成一个文本文件,比拆成四十个单页文件更好管理。
  • 去掉重复的版面元素。 识别工具经常把页脚变成每一页都出现的同一行文字。导入前删掉这些重复行,能改善关键词检索,原理和清洗器去掉电子 PDF 的重复页眉一样。

OCR 的错误会变成检索的错误

这一段值得读两遍。电子 PDF 里,错字根本进不了索引。扫描件里,识别结果决定了索引的内容,错误造成的差异是永久的——文档写的是什么和检索能搜到什么,从此对不上。

具体一点:如果识别引擎把保单号里的 0 认成 O,把编码里的 1 认成 l,或者把表格的两栏读成交错的行,那么按正确写法去搜,那一段就是搜不到。混合检索里负责救回精确标识的正是关键词那一半,而识别错误恰恰是它的克星。向量那一半也帮不上,稠密向量会把稀有词模糊掉,不会把它还原出来。

识别失败 对结果的影响 在哪里能发现
编号里数字与字母混淆 精确检索落空,只剩模糊的相关度排序在起作用 导入后立刻搜一次这个编号
双栏版面被读成交错行 句子变成词串,段落进了索引但读不成句 读一遍导入文本的第一页
表格整行被压成一行 列值和行标签的对应关系丢失 打开有表格的那一页看文本
变音符号或非拉丁文字被丢弃 词变成别的词,关键词检索失效 搜一个你在扫描件里看得见的普通词
阴影导致整块区域被识别成噪声 内容从索引里彻底缺失 对比识别文本的页数与扫描件的页数

导入后花两分钟自查能拦住大部分问题:打开你刚导进去的那个文本文件,对照扫描件读一遍第一页,再用你从原件上能读到的某个编号或名称,在工具里做一次精确检索。两项都过了,后面通常也在同一水平。

这些事它做不到

扫描件里本来就没有的内容,OCR 变不出来。模糊的一页、盖在签名线上的印章、页边的手写批注,识别结果往往是看似肯定的错误文本,或者干脆是空的。如果你的问题取决于一处手写标注,这份扫描件是搜不到的,只能由人去看图像。

还有一点要说清楚:这个工具不做 OCR。它解析你文件里已经存在的文本,而扫描件里没有文本。修这件事的环节在更上游,由你选择和掌控,那一步的质量决定了后面检索能力的上限。