将扰乱的 PDF 字符重新映射为可读文本

Mis*_*ong 2 python unicode character remap

我确实遇到了一个问题,因为 cups-PDF 创建的 PDF 文档中的字符被映射到奇怪的符号 [在 Ubuntu Linux 14.04 和 16.04 上]。我认为它是某种 unicode,即使 Python 告诉我它的字符串类型。type(object)蟒蛇返回"string"

\n\n

如果我通过鼠标复制粘贴从 evince / Firefox 或通过 Python PDFminer 模块从 PDF 中获取文本,则没有区别。所以确实如此,PDF 已经损坏了在 PDF 文档本身上正确呈现的文本信息。我不知道,但 PDF 文档中的文本和文本图形似乎并没有非常紧密地结合在一起。

\n\n

当我从这样创建的 PDF 文档中复制文本时,名称“Raphael”会变成"\xe2\x9c\xa1\xe2\x9c\x8d\xe2\x9c\x91\xe2\x9c\x92\xe2\x9c\x8d\xe2\x98\x9b\xe2\x9c\x93"这样,每个字符都会映射到"\xe2\x9c\xa1=R \xe2\x9c\x8d=a \xe2\x9c\x91=p \xe2\x9c\x92=h \xe2\x9c\x8d=a \xe2\x98\x9b=e \xe2\x9c\x93=l"

\n\n

另一个例子是:"Devel"变成"\xe2\x9c\xad\xe2\x98\x9b\xe2\x9c\xae\xe2\x98\x9b\xe2\x9c\x93"

\n\n

我怎样才能在Python中编写一个函数来将这个“错误”信息转换为正确的信息?PDF 文档中的所有内容都完全可读。

\n\n

这与 cups-PDF 使用 postscript 创建 PDF 但未向文档添加正确的字体/字符信息有关。

\n\n

如果字母始终是该复选标记 unicode 字符的\'l\'符号\'\xe2\x9c\x93\'

\n\n

如何将这种奇怪的表示形式中的字符重新映射为 Python 中的正确表示形式?那么如何将符号转换或重新映射\'\xe2\x9c\x93\'为字母\'l\'呢?任何想法?

\n\n

为什么我需要这个?\n我需要在此文档中搜索文本值。

\n

Mar*_*ers 9

PDF 似乎使用了专门的字体来防止复制。文字已乱码,但字体中的字母也是乱码的。因此,如果a一次映射到 Unicode 代码点 U+0061,则 PDF 会用 U+270D 替换所有这些 a,并且特殊字体会用字母 a 替换正常的“WRITING HAND”字形。

\n\n

换句话说,它使用替换密码

\n\n

您必须像任何其他替换密码一样对其进行解读:您需要创建从加密代码点到未加密代码点的反向映射。您可以使用 PDF 作为指南;作为人类,您可以轻松阅读实际文本,还可以了解它与复制的 Unicode 代码点的关系。

\n\n

例如,我们知道 U+270D 映射到 U+0061:

\n\n
>>> hex(ord(\'\xe2\x9c\x8d\'))\n\'0x270d\'\n>>> hex(ord(\'a\'))\n\'0x61\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

a因为当您从 PDF复制时,您得到的是270d代码点。只需为其余字母表建立一个表格即可。这听起来像是大量的手动工作,但您已经有了明文。想象一下不知道文本包含什么(例如,您只有复制文本产生的符号);那么你必须首先进行完整的密码分析(对于替换密码,假设一种特定的语言,并计算符号;每种语言的字母都有一个典型的频率分布,这种分布通常可以在加密体中匹配映射回原始字母的文本)。

\n\n

理论上,您应该能够提取专用字体,然后对其进行分析以生成翻译表。然而,这需要某种形式的计算机视觉;计算机不会轻易知道像素光栅或一系列矢量线形成特定的字母。对于大约 70 个代码点(大写、小写、数字、一些标点符号),手动创建表格可能会更容易。

\n\n

一旦你有了一个表,Python 就可以为你做翻译;我已经根据您的线索并为这些字母创建了一个部分表格:

\n\n
mapping = {\n    0x270d: \'a\',\n    0x261b: \'e\',\n    0x2712: \'h\',\n    0x2713: \'l\',\n    0x2711: \'p\',\n    0x272e: \'v\',\n\n    0x272d: \'D\',\n    0x2721: \'R\',\n}\n\nprint(encrypted.translate(mapping))\n
Run Code Online (Sandbox Code Playgroud)\n\n

您所需要做的就是填写剩余的映射;然后该str.translate()方法将处理其余的事情。

\n\n

在示例加密文本示例中使用上述部分表进行演示:

\n\n
>>> print("\xe2\x9c\xa1\xe2\x9c\x8d\xe2\x9c\x91\xe2\x9c\x92\xe2\x9c\x8d\xe2\x98\x9b\xe2\x9c\x93".translate(mapping))\nRaphael\n>>> print("\xe2\x9c\xad\xe2\x98\x9b\xe2\x9c\xae\xe2\x98\x9b\xe2\x9c\x93".translate(mapping))\nDevel\n
Run Code Online (Sandbox Code Playgroud)\n