PDF对企业应用来说是刚需。
 
然而PDF显然不是一种对机器友好的格式,它只是对人类友好,就是说方便阅读打印,但让程序去提取其中的内容却很难。下面简单说说为什么是这样。
 
以前还读书的时候(20+年前了),一个同学跟我展示了PDF文档,他说这种格式不是普通的文本,它是图片,所以比较大。其实他说的并不完全正确,pdf中可以包含图片,也可以包含文字,且其中的文字跟传统的位图还真是不一样。那么PDF中的内容究竟是什么?
以增值税普通发票的电子档为例,相信大家手头都有,对,就这个:

上面的文字究竟是图还是文本?上面的印章是不是位图?

判断是不是位图很简单,就是用一个PDF阅读器打开,Adobe的或者福昕的都行,选择“Select”工具,看看上面的文字能否选中。你很快就发现,不光上面的楷体字、宋体字能选中,印章里的文字居然也能选中,并且能复制下来,你把复制下来的文本贴到记事本里,这就是普通的文本。

这是不是就说明PDF里的文字就是我们常规理解的文本呢?其实没那么简单,PDF的一个特性就是不管处于怎样的环境,PDF都能显示出完整的、一致的内容。这意味着这张发票放到一个完全不支持中文的系统中,它也能显示出上面的汉字,并且效果完全一直,当然也包含了不同的字体,楷体,宋体,都没问题,这就比较厉害了。
 
其实原理也不难,那就是把字体信息直接嵌入到PDF文件内部。也许你觉得不对,我一个中文宋体的字库就有超过10MB了,而我的PDF才几百K,怎么可能?——要做到这点也不难,只嵌入部分即可。用福昕的PDF阅读器打开这张电子档发票,菜单"File" - "Properties" - "Fonts",你会看到这样的信息:

KaiTi,很明显是楷体,SimSun这是宋体,STSong则是华文宋体,而且编码格式都有,上面的UniGB-UCS2-H是什么编码格式我不太清楚,可能是Unicode,UC应该是Unicode的简写。
 
这里顺便提个事情,就是字体的侵权问题,如果在自己生成的PDF中嵌入字体厂商未授权的字体,很可能会造成侵权!而如果你做了一个网页,网页上指定了用未授权的字体(如微软雅黑)显示一段文字,这样则不会造成侵权,原因在于你并没有在网页上嵌入微软雅黑,你只是告诉用户的浏览器,这段文字建议用微软雅黑显示,用户看到的微软雅黑字体还是用户自己电脑提供的,跟你没有关系,所以不会造成侵权,侵不侵权在于你是否二次“发布”了这个字体。其实要避免侵权也不难,对我们来说,用可免费商用的字体即可,目前还不少,如Google的Noto系列,华为鸿蒙Sans、阿里巴巴普惠体以及小米最近发布的MiSans,这些都是可以免费商用的。
 
字体,本质上来说是矢量图,当然过去也曾经有过点阵字体,但现在基本算是淘汰了,矢量图一个特点是无论你放大多少倍,它都不会失真或出现马赛克,所以一定要我说PDF中保存的文字到底是图还是字,那我就说,那是矢量图,这肯定是正确的,因为如今的字体本质上就是矢量图嘛。
 
而PDF中除了字之外,别的你能看到的很多的元素,其实也都是矢量图,如表格的线条,印章的圆圈这些,要证明也很简单,使劲放大,看看有没有失真出现马赛克或者模糊即可。
 
当然了PDF中还可能有位图,判断方法还是上面提到的,放大来看。
 
PDF的文字的组织形式与我们txt,word或是html都不太一样,举个例子,你打开PDF看到的两个挨在一块的文字,如“力量”,这两个字你觉得它是一个连在一起的词,其实未必,很可能它是通过两个不同的坐标来指定的,从文档结构上来说,你读取“力”字,不意味着它的下一个元素就一定是“量”字,尽管视觉上是这样。这就给我们提取PDF的文本信息带来很大的挑战,我们很难通过直接分析PDF的文档结构提取其中的文字,比较稳妥的方法还是得通过显示的结果来获取内容,是的,就是OCR的路线。但即便要使用OCR的路线,也是问题很多,下面这个例子就反映了一个很典型的问题:

阅读器显示的“μ”和“接”中间的这个符号在我看来很像一个竖线,即“|”,而实际上它却是英文字母“l”,用阅读器复制到记事本中可以证实这点,确实是字母“l”,只不过Windows10种的字母“l”显示得跟数值“1”一模一样,真是令人无语,如果使用OCR的方式,字母“l”很可能就被识别为竖线,或者字母“I”(大写的i),还有就是“μ”这种希腊字母,在OCR中直接被识别成了英文字母“u”,这就很明显有问题了,对于需要精确导入信息的企业应用来说,这显然是不行的。
 
另一个问题也在上图中有体现,就是对空格的理解,福昕阅读器复制出来的内容中包含了一个空格,而别的没有,究竟有没有这个空格,这个很难说,就像我在黑板上写了两个字,间隔远点就算有空格,间隔近了就没有空格,可这个远和近如何界定,这个就比较难办了。
 
我曾经做过一套PDF内容提取的框架,能通过一些配置信息尝试从PDF中提取文本内容,但遇到了很大的麻烦,就如上面提到的那样,两个看上去连贯的文字,读出来的先后顺序是没法保证的,绕来绕去还绕回了OCR的路子,但OCR也是问题不少,总得来说,对于需要精准信息提取的应用来说,真是最好别用PDF了。——但话虽然这么说,客户可不一定能理解,做和不做也不完全由得技术说了算,现实如此也……

PDF的信息提取的问题的更多相关文章

  1. Beta版本发布说明

    发布地址 https://github.com/LongWerLingShi/DataObtainingAndHandling/tree/beta 版本开发背景 首先,应软件工程课程要求,我们小组针对 ...

  2. 数据获取以及处理系统 --- 功能规格说明书V2.0

    产品规格说明书: 版本号: V2.0 版本说明: Version 1.0 简单得需求分析以及构思,初稿形成 Version 2.0 细化beta阶段设计,增加典型用户尝尽以及功能罗列 1. 引言 1. ...

  3. Scrum Meeting 11 -2014.11.17

    今天和其他两个小组讨论了关于整合问题,在数据库连接等具体方面上还需要继续商讨. 我们小组内部讨论了,这周还是需要在处理整合的同时做项目整体的测试与改进的. Member Today’s task Ne ...

  4. Scrum Meeting 10 -2014.11.16

    开始进入大项目的整合阶段,平时和其他两个小组交流较少,整合难度还是存在的. 在具体整合前,让开发人员添加了些必要的注释,优化代码结构,方便阅读. Member Today’s task Next ta ...

  5. Scrum Meeting 9 -2014.11.15

    项目开发测试要进入尾声了.大家加把劲,这周末能整合完成就最好了. 服务器方面已经能运行我们的程序了.还需要研究如何与其他两小组整合. Member Today’s task Next task 林豪森 ...

  6. Scrum Meeting 8 -2014.11.14

    给开发加了个pdf信息提取优化任务. 弄了半天发现服务器也是个好东西.这周末可以和爬虫讨论整合的问题了. Member Today’s task Next task 林豪森 协助测试及服务器部署 协助 ...

  7. Scrum Meeting 7 -2014.11.13

    之前srcum没写好是我的错.以后会每天更新的. 老师反映之前项目小组从pdf中提取作者效果不好,我们讨论决定进行一定的优化.在整合测试的同时开始服务器程序部署. Member Today’s tas ...

  8. 会务准备期间材料准备工作具体实施总结 ----(vim技巧应用, python信息提取与整合, microsoft word格式调整批量化)

    会务准备期间材料准备工作具体实施总结(vim, python, microsoft word) span.kw { color: #007020; font-weight: bold; } code ...

  9. C#给PDF文档添加文本和图片页眉

    页眉常用于显示文档的附加信息,我们可以在页眉中插入文本或者图形,例如,页码.日期.公司徽标.文档标题.文件名或作者名等等.那么我们如何以编程的方式添加页眉呢?今天,这篇文章向大家分享如何使用了免费组件 ...

随机推荐

  1. Linux基础命令---mysqldump数据库备份

    mysqldump mysqldump是一个客户端的备份程序,他可以备份数据库,或者将数据库传输到另外一个服务器. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. ...

  2. 【编程思想】【设计模式】【行为模式Behavioral】chain

    Python版 https://github.com/faif/python-patterns/blob/master/behavioral/chain.py #!/usr/bin/env pytho ...

  3. 【JAVA】【基础知识】Java程序执行过程

    1. Java程序制作过程 使用文本编辑器进行编辑 2. 编译源文件,生成class文件(字节码文件) javac源文件路径. 3.运行程序class文件.

  4. 一文读懂RESTful架构

    转载自https://zhuanlan.zhihu.com/p/381554129 RESTful架构究竟是什么 别着急,想要了解RESTful,我们先来了解一位大佬Roy Thomas Fieldi ...

  5. JDBCUtils工具类的属性

    package cn.itcast.util;import java.io.FileReader;import java.io.IOException;import java.net.URL;impo ...

  6. 全面解析 | 钥匙环服务的应用场景&商业价值

    在互联互通的场景驱动下,同一开发者旗下常常拥有多款应用或者多个应用形态,用户在同一设备的不同应用或端口登录时,即便使用同一帐号,仍需要重复输入密码进行验证,操作复杂,直接影响到用户的使用体验,而华为钥 ...

  7. 网络协议之:基于UDP的高速数据传输协议UDT

    目录 简介 UDT协议 UDT的缺点 总结 简介 简单就是美.在网络协议的世界中,TCP和UDP是建立在IP协议基础上的两个非常通用的协议.我们现在经常使用的HTTP协议就是建立在TCP协议的基础上的 ...

  8. 『学了就忘』Linux服务管理 — 79、源码包安装的服务管理

    目录 1.源码包服务的启动管理 2.源码包服务的自启动管理 3.让源码包服务被服务管理命令识别 1.源码包服务的启动管理 # 通过源码包的安装路径,找到该服务的启动脚本, # 也就是获得该服务的启动脚 ...

  9. 转:UITableView学习笔记

    UITableView学习笔记        作者:一片枫叶 看TableView的资料其实已经蛮久了,一直想写点儿东西,却总是因为各种原因拖延,今天晚上有时间静下心来记录一些最近学习的 TableV ...

  10. 区块链开发学习第七章:第一个Dapp-猜拳游戏

    第一个简单的Dapp-猜拳游戏.本智能合约的功能很简单,就是用户与电脑猜拳,用户选择出手后,电脑随机一个选项,然后调用智能合约方法把两个选项值传过去,在智能合约上进行比较,并通过区块链合约事件广播结果 ...