3

在我正在进行的一个项目中,我们从各个政府网站上抓取法律文件,然后让它们可以在线搜索。

我们时不时会遇到一个似乎已损坏的 PDF。这是一个示例

如果您在 PDF 阅读器中打开它,它看起来不错,但是:

  • 如果您尝试复制并粘贴它,则会收到损坏的文本
  • 如果您通过 pdftotext 之类的任何工具运行它,则会损坏文本
  • 如果你对它做任何其他事情——你猜对了——你会得到损坏的文本

但是,如果您在阅读器中打开它,它看起来还不错!所以我知道文字在那里,但有些地方不对,不对不对!结果是在我的网站上它看起来非常糟糕。

有什么我可以做的吗?

更新:我今天做了更多的研究。感谢@Andrew Cash 观察到这本质上是一个凯撒密码,我意识到我可以搜索这些文件。此链接将在我的系统中向您展示其中的大约 200 个。查看更大的样本集,看起来这些都是由同一个软件 pdffactory v. 3.51 创建的!所以我责怪一个错误,而不是故意混淆。

更新 2:上面的链接将不再提供任何结果。这些是使用下面的解决方案从我的系统中清除的。

4

2 回答 2

3

Tha PDF 使用子集字体,其中字符使用与简单的二战替换密码相同的方式重新映射到其他字符。

A = G,B = 1,C = #,D = W,……等等。每个角色都被重新映射。

字体以这种方式映射,为了在 PDF 中显示正确的字符,您需要发送“G1#W”以打印 ABCD。通常 PDF 会有一个 ToUnicode 表来帮助您进行文本提取,但我怀疑这个表是故意遗漏的。

我自己也看过其中一些文档,它们被故意混淆以防止文本提取。我看过一个包含大约 5 种不同字体的文档,它们都使用不同的顺序映射。

判断这是否是问题的一种可靠方法是将 PDF 加载到 Acrobat 中并将文本复制/粘贴到文本编辑器中。如果 Acrobat 无法将文本解码回英文,那么如果您知道翻译映射,则无法在不手动重新映射的情况下提取文本。

从这些类型的文档中轻松提取文本的唯一方法是对整个文档进行 OCR 并删除原始文本。OCR 会将页面转换为 TIFF 图像,然后对其进行 OCR,因此原始乱码文本不应影响 OCR。

于 2012-02-10T07:37:13.617 回答
2

厌倦了这个问题,不想处理 OCR,我手动整理了密码。她在这里,作为一个 python 字典以及我用来测试它的一些基本代码。我确信这可以改进,但它确实适用于除大写 Q 和大写 X 之外的所有字母,我还没有找到。

至少现在它也缺少一些标点符号(所有这些都缺少,例如:<>?{}\|!~`@#$%^_=+)。

# -*- coding: utf-8 -*-

import re
import sys

letter_map = {
 u'¿':'a',
 u'regex':'b',
 u'regex':'c',
 u'regex':'d',
 u'»':'e',
 u'o':'f',
 u'1':'g',
 u'regex':'h',
 u'·':'i',
 u'¶':'j',
 u'μ':'k',
 u'regex':'l',
 u'3':'m',
 u'2':'n',
 u'±':'o',
 u'°':'p',
 u'regex':'q',
 u'®':'r',
 u'-':'s',
 u'¬':'t',
 u'«':'u',
 u'a':'v',
 u'©':'w',
 u'regex':'x',
 u'§':'y',
 u'¦':'z',
 u'ß':'A',
 u'Þ':'B',
 u'Ý':'C',
 u'Ü':'D',
 u'Û':'E',
 u'Ú':'F',
 u'Ù':'G',
 u'Ø':'H',
 u'×':'I',
 u'Ö':'J',
 u'Õ':'K',
 u'Ô':'L',
 u'Ó':'M',
 u'Ò':'N',
 u'Ñ':'O',
 u'Ð':'P',
 u'':'Q', # Missing
 u'Î':'R',
 u'Í':'S',
 u'Ì':'T',
 u'Ë':'U',
 u'Ê':'V',
 u'É':'W',
 u'':'X', # Missing
 u'Ç':'Y',
 u'Æ':'Z',
 u'ð':'0',
 u'ï':'1',
 u'î':'2',
 u'í':'3',
 u'ì':'4',
 u'ë':'5',
 u'ê':'6',
 u'é':'7',
 u'è':'8',
 u'ç':'9',
 u'ò':'.',
 u'ô':',',
 u'æ':':',
 u'å':';',
 u'Ž':"'",
 u'•':"'",
 u'•':"'", # s/b double quote, but identical to single.
 u'Œ':"'", # s/b double quote, but identical to single.
 u'ó':'-', # dash
 u'Š':'-', # n-dash
 u'‰':'--', # em-dash
 u'ú':'&',
 u'ö':'*',
 u'ñ':'/',
 u'÷':')',
 u'ø':'(',
 u'Å':'[',
 u'Ã':']',
 u'‹':'•',
 }

ciphertext = u'''YOUR STUFF HERE'''

plaintext = ''

for letter in ciphertext:
    try:
        plaintext += letter_map[letter]
    except KeyError:
        plaintext += letter

# These are multi-length replacements
plaintext = re.sub(u'm⁄4', 'b', plaintext)
plaintext = re.sub(u'g⁄n', 'c', plaintext)
plaintext = re.sub(u'g⁄4', 'd', plaintext)
plaintext = re.sub(u' ́', 'l', plaintext)
plaintext = re.sub(u' ̧', 'h', plaintext)
plaintext = re.sub(u' ̈', 'x', plaintext)
plaintext = re.sub(u' ̄u', 'qu', plaintext)

for letter in plaintext:
    try:
        sys.stdout.write(letter)
    except UnicodeEncodeError:
        continue
于 2012-02-10T22:39:15.690 回答