在 PDF 中添加链接

Joe*_*nin 3 python regex pdf string text

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

  1. 使用正则表达式在 PDF 文本中查找匹配项。
  2. 将匹配文本转换为指向外部 URL 的链接。
  3. 保存新版本的 PDF。

如果我在 HTML 中执行此操作,它将如下所示:

<!-- before: -->
This is the text to match.

<!-- after: -->
This is the text to <a href="http://www.match.com/" target="_blank">match</a>.
Run Code Online (Sandbox Code Playgroud)

如何对 PDF 执行此操作?

我更喜欢 Python,但我对其他选择持开放态度。

编辑:我无权访问原始 Word 文档。我需要自己操作 PDF。我正在寻找一种使用 Python PDF 库(或其他语言中的类似库)的技术。

编辑 2:我知道 PDF 的源代码不包含文字字符串。我想知道是否有一种方法可以执行以下操作:(1)提取文本,(2)查找匹配项,以及(3)对于每个匹配项,在原始 PDF 中的文本位置周围绘制一个可点击的框。我最接近的是 PyPDF2 的addLink(),但它在 PDF中添加了内部链接,而不是指向外部 URL 的链接。

Kur*_*fle 5

1. 'regex'方法不起作用!

你有什么“想”“使用正则表达式来查找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
Run Code Online (Sandbox Code Playgroud)

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

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


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

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

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

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

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

  2. 您可以使用TET,该文本提取工具包,找到匹配的单词的精确坐标了。TET 甚至可以为您提供单个字形的坐标。

  3. 一旦确定了匹配项的位置,您就可以使用PDFlib添加链接。


小智 5

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

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

我的 PyPDF2 分支具有addURI功能,其工作方式与包的原始addLink().

具体来说:使用具有页码键的矩形字典:

rectangles_dictionary = {0:{'key1':[255, 156, 277, 171],'key2':[293, 446, 323, 461]},1:{'key2':[411, 404, 443, 419]}}
Run Code Online (Sandbox Code Playgroud)

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

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

destinations_dictionary = {'key1':'url1','key2':'url2'}
Run Code Online (Sandbox Code Playgroud)

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

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

使用 JSON 或其他东西来完成前半部分的更简洁的方法,但对于我的实现来说,这是最有效的方法。

关键的一行当然是这一行:

result.addURI(pagenum, destination, rectangle)
Run Code Online (Sandbox Code Playgroud)

其中pagenumas int()、目的地为str()、矩形为list()

  • 如何找到用于给定文本的矩形值? (2认同)