在开始这样一个雄心勃勃的项目之前,您应该让自己熟悉完整 official PDF-1.7 specification。请注意:这是一个 756 页的文档,它引用了大约 90 个其他文档,它声明它们也是 PDF 的“规范”。
您将了解到,为了将 PDF 源代码反转为文本内容,您必须反向应用字体使用的 编码。可以使用 5 种规范定义的标准编码:
StandardEncoding
MacRomanEncoding
WinAnsiEncoding
PDFDocEncoding
MacExpertEncoding
除此之外,还可以有 CustomEncoding(当嵌入字体是子集时发挥作用,并且不包含字体定义的所有字形,但仅包含那些文件要求的字形)。如果在 PDF 中定义了 /ToUnicode 表,则只能反转 CustomEncode-d 文本。只有这样,您才能将编码字符反向映射到字符名称。
您还将了解到,不仅有 一个,还有 四个 运算符可用于显示文本字符串:
-
Tj:“显示文字”
-
TJ:“显示文本,允许单独的字形定位”
-
':“移动到下一行并显示文本”
-
" : “设置单词和字符间距,移动到下一行,并显示文本”
此外,有三种不同的方式来表示文本字符串。这里给出了字符串 "string" 的示例:
-
(string):这在括号内使用标准可打印 ASCII 字符(仅适用于拉丁/ASCII 文本部分)。
-
(\163\164\162\151\156\147) :这使用 八进制 字符代码(也在括号内),如“附录 D(规范)字符集和编码”中列出的规范文件。
-
<737472696E67> :这使用尖括号内的十六进制编码字符代码。
文本提取器的问题如下:
-
使用可打印的 ASCII 字符(上面的1.)和八进制字符代码(上面的2. ) 可以混合。以下所有内容也是字符串 "string" 的“合法”表示(列表不完整!):
(\163tring)Tj
(\163\164\162\151\156g) Tj
(st\162i\156g) Tj
...
-
使用十六进制编码的字符代码(上面的3.)也不是直截了当的,因为以下所有表示都是等价的:
<73 74 72 69 6E 67> TJ
<73 7472 696E67> TJ
<7 374 7 269 6E 67>TJ
<73 74 72696E 67> TJ
<73
74 7
2 69 6E 67>
TJ
有关 PDF 规范允许(或 Adobe 查看器允许)的更多怪异,另请参见示例:
我自己最近创建了一系列手工编码的 PDF 文件,这些文件展示了丢失、不正确、被操纵或正确的 /ToUnicode 表如何影响任何 PDF 到文本反转的结果:
最后看一下OP提供的PDF源代码的小sn-p:
BT
56.8 721.3 Td
/F2 12 Tf
[<01>2<0203>2<04>-10<0503>2<04>-2<0506070809>2<0A>1<0B>]TJ
ET
BT 和ET 表示文本显示部分的开始和结束
56.8 721.3 Td将当前点定位到坐标“水平方向56.8点,垂直方向721.3点”。
12 Tf 将字体大小设置为 12 磅。
/F1 将要使用的字体设置为 PDF 文档中其他地方定义的字体。该字体还在某处设置了字体编码(可能还有/ToUnicode 表)。当在文本字符串中看到特定的字符代码时,字体编码将确定应绘制哪种字形。
[<01>2<0203>2<04>-10<0503>2<04>-2<0506070809>2<0A>1<0B>]TJ
这最后一部分可以分为以下几部分:
-
<01>2 :<01> 是第一个字符代码。 2 是使用文本显示运算符TJ 时允许的“单独字形定位”的参数。
-
<0203>2 :<0203> 是另外两个字符代码。 2 又是TJ 的“个别字形定位”的参数。
-
<04>-10 :<04> 是第四个字符代码。 -10 再次用于 “个别字形定位”,TJ。
-
<0503>2:<05>是第五个字符代码,<03>是第三个字符代码(之前用过)。 2 用于“个别字形定位”...
- 等
个别字形定位:个别字形定位的工作原理如下:
-
正数将下一个字形移到左(减小字形间距到下一个字形)。
-
负数将下一个字形移到右侧(为下一个字形添加更多空间)。
- 数字本身代表当前单位的千分之一。
字符代码的含义:要了解第一个、第二个、第三个……最后一个字符代码的含义,您必须在 PDF 的 /ToUnicode 表中查找这些代码。如果它没有嵌入这样的表,那就倒霉了!
检查文本是否易于提取:要检查您的 PDF 是否适合文本提取,您可以使用命令行工具 pdffonts。这是一个示例输出:
$ pdffonts sample.pdf
name type encoding emb sub uni object ID
------------------------- ------------- ------------ --- --- --- ---------
IADKRB+Arial-BoldMT CID TrueType Identity-H yes yes yes 10 0
SSKFGJ+ArialMT CID TrueType Custom yes yes no 11 0
在上述示例中,子集字体 SSKFGJ+ArialMT 使用自定义编码,但 PDF 中没有此字体的 /ToUnicode,如标题为 uni 的列所示。因此,提取使用此字体显示的文本并不容易(提取需要手动逆向工程——但您也可以只“阅读”PDF 页面)。