编码PDF文本字符串

duc*_*kgo 10 pdf

我正在研究PDF(文本提取)的解析器.

当页面需要Flate Decoded(来自zlib压缩)时,我的代码能够解压缩内容流,然后我有输出(流对象),如下所示:

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
Run Code Online (Sandbox Code Playgroud)

我对字符串数组(TJ的操作数)感兴趣.

看起来这个数组中包含多个十六进制编码的字符串,但相应的十六进制值没有意义.相反,它出现了像010203这样的序列......类似于lz77压缩.

  • PDF有多级压缩吗?
  • 如何从字符串数组中获取纯文本?

Kur*_*fle 51

在开始这样一个雄心勃勃的项目之前,您应该熟悉完整的 官方PDF-1.7规范.请注意:这是一份756页的文档,它引用了大约90个其他文档,它们声称它们也是PDF的"规范"文档.

您将了解到,为了将PDF源代码反转为文本内容,您必须反向应用字体使用的编码.可以使用5种规范定义的标准编码:

  1. StandardEncoding
  2. MacRomanEncoding
  3. WinAnsiEncoding
  4. PDFDocEncoding
  5. MacExpertEncoding

最重要的是,还可以有一个CustomEncoding(当嵌入字体是子集时,它会发挥作用,并且不包含字体定义的所有字形,但只包含文档所需的字形).如果/ToUnicode在PDF中定义了表,则只能反转CustomEncode-d文本.只有这样,您才能将编码的字符反向映射到字符名称.

您还将了解到,不仅有一个,而且有四个运算符可用于显示文本字符串:

  1. Tj:"显示文字"
  2. TJ:"显示文本,允许单独的字形定位"
  3. ':"移至下一行并显示文字"
  4. ":"设置单词和字符间距,移动到下一行,并显示文本"

此外,有三种不同的方式来表示文本字符串.这里给出了字符串"string"的示例:

  1. (string):这在括号内使用标准的可打印 ASCII字符(仅适用于拉丁文/ ASCII文本部分).
  2. (\163\164\162\151\156\147):这使用八进制字符代码(也在括号内),如规范文档的"附录D(规范)字符集和编码"中所列.
  3. <737472696E67>:这在尖括号内使用十六进制编码的字符代码.

文本提取器的问题如下:

  1. 可以混合使用可打印的ASCII字符(1.上面)和八进制字符代码(2.上面).以下所有内容也是字符串"string"的 "合法"表示(列出不完整!):

     (\163tring)Tj
     (\163\164\162\151\156g) Tj
     (st\162i\156g)  Tj
     ...
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用十六进制编码的字符代码(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
    
    Run Code Online (Sandbox Code Playgroud)

对于PDF规范允许的更多怪异(或Adobe观众容忍),请参阅例如:

我自己最近创建了一系列手工编写的PDF文件,演示了丢失,不正确,操作或正确的/ToUnicode表如何影响任何PDF-to-Text反转的结果:


最后,看一下OP提供的一小段PDF源代码:

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
Run Code Online (Sandbox Code Playgroud)
  • BTET指出显示部分的文本的开头和结尾

  • 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是使用文本show运算符时允许的"单个字形定位"的参数TJ.
  • <0203>2:<0203>还有两个字符代码.2再次是对参数"个人字形定位"TJ.
  • <04>-10: <04>是第四个字符代码.-10再次为"个体雕文定位"搭配TJ.
  • <0503>2: <05>是第五个字符代码,<03>是第三个字符代码(之前使用过).2用于"个体字形定位" ......
  • 等等

单个字形定位:单个字形定位的工作方式如下:

  • 数将下一个字形向左移动(将字形间距减小到下一个字形).
  • 负数将下一个字形向右移动(为下一个字形添加更多空格).
  • 数字本身将被视为当前单位的千分之一.

字符代码的含义:要知道第一个,第二个,第三个,......最后一个字符代码的含义,您必须在/ToUnicodePDF表格中查找这些代码.如果它没有嵌入这样的表,那么运气不好!

检查文本的易提取性:要检查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
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,子集化字体SSKFGJ+ArialMT使用自定义编码,但PDF没有/ToUnicode此字体,如标题列所示uni.因此,提取用这种字体显示的文本并不容易(提取需要手动逆向工程 - 但是你也可以"阅读"PDF页面).


Dav*_*che 5

阿比舍克

这不是一个简单的问题,不幸的是,它表明您尚未阅读PDF规范。您应该这样做。

您可以在此处下载Acrobat SDK:http//www.adobe.com/devnet/acrobat/sdk/eula.html

其中一部分是PDF规范,这是一个非常繁重的文档,解释了PDF的来龙去脉(包括对问题的回答)。

简而言之,而不是代替阅读文档,您正在寻找的是/ F2 12 Tf命令设置的字体编码中的字符值,该命令设置了随后编写文本时使用的特定字体。