添加PDF格式的链接

时间:2015-03-01 17:42:00

标签: python regex string pdf text

我有几个用Microsoft Word生成的PDF。我想:

  1. 使用正则表达式在PDF文本中查找匹配项。
  2. 将匹配的文本转换为指向外部URL的链接。
  3. 保存新版PDF。
  4. 如果我在HTML中这样做,它将如下所示:

    <!-- before: -->
    This is the text to match.
    
    <!-- after: -->
    This is the text to <a href="http://www.match.com/" target="_blank">match</a>.
    

    如何对PDF进行此操作?

    我更喜欢Python,但我可以接受替代方案。

    修改:我无法访问原始Word文档。我需要自己操纵PDF。我正在寻找使用Python PDF库(或其他语言类似的东西)的技术。

    编辑2:我知道PDF的源代码不包含文字字符串。我想知道是否有一种方法可以做类似的事情:(1)提取文本,(2)找到匹配,(3)对于每个匹配,在该位置周围绘制一个可点击的框。原始PDF中的文字。我最接近的是PyPDF2的addLink(),但这会在PDF中添加内部链接,而不是指向外部网址的链接。

3 个答案:

答案 0 :(得分:4)

1。 &#39; regex&#39; 方法无法工作!

想要&#39; &#39;使用正则表达式查找PDF中的匹配项是不可能的!简单明了的答案。

<强>理由:

对于一般情况,您无法使用正则表达式来查找匹配项。在PDF文本中。我甚至不会在这里讨论Unicode字符...

我只会考虑您问题中示例的简单文字字符串:match

在PDF源代码中,此字符串可能以不同的形式出现,具体取决于PDF生成软件以及使用字体编码的确切字体。以下列表尚未完成!

(match) Tj                       # you are lucky
<6d61746365> Tj                  # hex representation of characters
<6d 61 74 63 65> Tj              # hex representation of characters, v2
<6d   61 7463   65> Tj           # hex representation of characters, v3
<6d>Tj <61>   Tj<746365>Tj       # hex representation of characters, v4
....                             # skipping version 5-500000000 of all... 
                                         # ...possible hex representations
(\155\141\164\143\150) Tj        # octal representation of characters
(m\141\164ch) Tj                 # octal/ascii mixed representation of chars
(\155a\164ch) Tj                 # octal/ascii mixed representation of chars, v3
<6d 61>Tj (\164c\150) Tj         # hex/octal/ascii mix
....                             # skipping many more possibilities

如果字符串应该使用的字体确实使用了自定义编码,那么它会变得更加复杂(就像将字体作为子集嵌入PDF中的情况一样) em> - 仅包含在相应文本中使用的这些字形)。

这可能意味着上面<6d61746365> Tj的内容可能会使用自定义编码字体成为<2234567111> Tj,但它仍会在PDF页面上显示match


2。实现类似结果的变通方法可能有效

  1. 您可以使用pdftotext -layout some.pdf some.txt创建包含PDF文本的文件。 (这不能可靠地工作。某些PDF,例如那些缺少有效/ToUnicode表格的PDF,不会很容易用于文本提取。)

    这可以引导您找到匹配的页码。

    使用(通过一些试用&#39; n&#39;错误)pdftotext -f 33 -l 33 -layout -x NN -y MM -W NN -H MM可以更准确地缩小第33页的匹配位置。

    使用pdftotext -layout -bbox -f 33 -l 33将返回第33页上每个单词的边界框的坐标。

  2. 您可以使用 TET 文本提取工具包来查找匹配单词的确切坐标。 TET甚至可以为您提供各个字形的坐标。

  3. 确定匹配位置后,您可以使用 PDFlib 添加链接。

答案 1 :(得分:1)

我已经解决了这个问题。感谢任何人清理任何错误。 https://github.com/JohnMulligan/PyPDF2/tree/URI-linking

因为Kurt回答了第1部分和第2部分的大部分内容,所以我将限制我对原始问题第3部分的回答:如何向PDF添加外部链接。 (我对1&amp; 2有一个完全正常的答案,但它不够优雅。如果人们想要它,我也会发布它。)

我的PyPDF2分支具有addURI功能,其功能与原始程序包addLink()相同。

具体做法是: 使用具有pagenumber键的矩形字典:

rectangles_dictionary = {0:{'key1':[255, 156, 277, 171],'key2':[293, 446, 323, 461]},1:{'key2':[411, 404, 443, 419]}}

(矩形格式为[llX, llY, urX, urY]) 现在我们有了矩形,可以为第1页分配2个矩形,在第2页分配1个矩形。

添加一个URL字典,该字典使用这些键来查找要分配的URL:

destinations_dictionary = {'key1':'url1','key2':'url2'}

然后我们可以为所有这些矩形区域添加适当的链接:

def make_pdf(rectangles_dictionary,destinations_dictionary):
    input = reader(file('pdfs/input_pdf.pdf','rb'))
    output = file('pdfs/output_pdf.pdf','wb')
    result = writer()

    for pagenum in range(0, input.getNumPages()):
        page = input.getPage(pagenum)
        result.addPage(page)

    for pagenum in rectangles_dictionary.keys():

        for name in rectangles_dictionary[pagenum].keys():
            for rectangle in rectangles_dictionary[pagenum][name]:

                    destination = destinations_dictionary[name]
                    result.addURI(pagenum, destination, rectangle)

    result.write(output)

使用JSON或其他方法在上半场做更清洁的方法,但对于我的实现,这是最有效的方法。

当然,关键在于:

result.addURI(pagenum, destination, rectangle)

pagenumint(),目标为str(),矩形为list()

答案 2 :(得分:0)

由于PDF是二进制格式,正则表达式不是解决此问题的正确方法。您需要使用可以读写pdf文件的python pdf库。起点可以是this SO question