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

Python 将加扰的PDF字符重新映射为可读文本,python,unicode,character,remap,Python,Unicode,Character,Remap,我确实有一个问题,因为cups PDF创建PDF文档时,字符被映射到奇怪的符号[在Ubuntu Linux 14.04和16.04上]。我认为这是某种unicode,即使Python告诉我它的字符串类型。type(object)Python返回“string” 如果我通过evince/Firefox的鼠标复制粘贴或Python PDFminer模块从PDF中获取文本,没有什么区别。因此,这是真的,PDF破坏了在PDF文档本身上正确呈现的文本信息。我不知道这一点,但PDF文档上的文本和文本图形似乎

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

如果我通过evince/Firefox的鼠标复制粘贴或Python PDFminer模块从PDF中获取文本,没有什么区别。因此,这是真的,PDF破坏了在PDF文档本身上正确呈现的文本信息。我不知道这一点,但PDF文档上的文本和文本图形似乎没有紧密结合在一起

当我通过示例从创建的PDF文档中复制文本时,“Raphael”的名称会变成
✡✍✑✒✍☛✓"因此每个字符都映射到
“✡=R✍=A.✑=P✒=H✍=A.☛=E✓=l“

另一个例子是:
“Devel”
变成了
”✭☛✮☛✓“

如何用Python编写一个函数,将这些“错误”的信息转换为正确的信息?在PDF文档中,所有内容都是完全可读的

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

如果字母
'l'
始终是符号
'✓'这是哪一个

如何将这个奇怪表示法中的字符重新映射到Python中的正确表示法?那么,如何移动或重新映射符号
✓'字母
'l'
?有什么想法吗?

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

PDF似乎使用了专门的字体来防止复制。文本被置乱,但字体中的字母也被置乱。因此,如果
a
一旦映射到Unicode代码点U+0061,PDF将用U+270D替换所有这些a,并且特殊字体替换了普通字体“用字母a书写“手”字形

换句话说,它使用的是一个

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

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

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

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

一旦您有了一个表,Python就可以为您进行翻译;我根据您的提示,为这些字母创建了一个部分表:

mapping = {
    0x270d: 'a',
    0x261b: 'e',
    0x2712: 'h',
    0x2713: 'l',
    0x2711: 'p',
    0x272e: 'v',

    0x272d: 'D',
    0x2721: 'R',
}

print(encrypted.translate(mapping))
您所需要做的就是填写其余的映射;然后将处理其余的映射

使用上述部分表格演示您的示例加密文本示例:

>>> print("✡✍✑✒✍☛✓".translate(mapping))
Raphael
>>> print("✭☛✮☛✓".translate(mapping))
Devel

是的,PDF似乎使用了一种专门的字体来防止复制。文本被置乱,但字体中的字母也被置乱。因此,如果
a
一旦映射到Unicode代码点U+0061,PDF将用U+270D替换所有这些a,而特殊字体则替换了正常的“手写体”带有字母a的字形。这是一个替换密码。你说得对。Martijn Pieters a等于unicode“U+270D”,我如何解扰该文本?我如何将这些字母映射回它们的原始值?a现在是“U+270D”返回到“U+0061”?附近有Python函数吗?非常好而且详细的说明。也许我现在可以参加周六的婚礼了。如果没有你的帮助,我无法及时完成。--非常感谢你--我会用Python2.7试试这个,很快会回复的!@MisterWong:确保你使用
unicode
字符串;
str.translate()
unicode.translate()
方法的签名不同。上面的代码适用于Python 3和Python 2
unicode.translate()