在 PDF 中添加链接 [关闭]

Posted

技术标签:

【中文标题】在 PDF 中添加链接 [关闭]【英文标题】:Add links in PDF [closed] 【发布时间】:2015-05-02 00:57:31 【问题描述】:

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

    使用正则表达式在 PDF 文本中查找匹配项。 将匹配文本转换为指向外部 URL 的链接。 保存新版本的 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>.

如何对 PDF 执行此操作?

我更喜欢 Python,但我对替代品持开放态度。

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

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

【问题讨论】:

在原始 Word 文档中执行此操作可能会更好。例如,您的第一点“使用正则表达式在 PDF 文本中查找匹配项”已经不适合对 PDF 进行操作。 我无法访问原始 Word 文档。我只有 PDF。 我不“明白”为什么一些 SO 用户会否决这个问题并投票甚至关闭它。因为他们自己不知道答案?!?这个问题的潜在答案不太可能对该平台产生争议或负面影响。那为什么呢? PDF 中的链接是注释。如果 1.5 年前的解决方案有效,即在您想要链接的地方添加突出显示注释,那么该代码只需要非常小的修改(尽管我现在正在看它,但我会重新编写它,但这是另一个故事)并且,真的,你没有太多的努力。您打算如何在不打开 PDF 参考的情况下使用 Python PDF 库 【参考方案1】:

我已经解决了这个问题。感谢任何清理任何错误的人。 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]

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

添加一个使用这些键查找要分配的 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()

【讨论】:

如何找到用于给定文本的矩形值?? 我找不到那部分的旧代码。但库尔特在下面的回答指出了正确的方向。如果我没记错的话,你应该提取每一个文本字符,记录它们的 x/y 坐标并使用字体数据作为高度/宽度增量。然后将它们编译成带有来自这些坐标的边界框的单词。然后,您可以搜索已构建的匹配文本,并返回边界框。我想! 这个问题已经过时且已关闭,但对于那些寻求将外部链接添加到 PDF 的解决方案的人,请尝试 PyFPDF,其中函数 fpdf.link 可以链接到外部 URL。【参考方案2】:

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

'想要''使用正则表达式在 PDF 中查找匹配'不可能! strong> 简单明了的答案。

原因:

对于一般情况,您不能使用正则表达式在 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> - 仅包含在相应文本中使用的这些字形)。

这可能意味着上面的 &lt;6d61746365&gt; Tj 可能会变成带有自定义编码字体的 &lt;2234567111&gt; Tj,但它仍会在 PDF 页面上显示 match


2。实现相似结果的变通办法可能会奏效

    您可以使用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 页上匹配的位置。

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

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

    确定比赛地点后,您可以使用 PDFlib 添加链接。

【讨论】:

对。我了解 PDF 的源代码不包含文字字符串。我想知道是否有一种方法可以执行以下操作:(1)提取文本,(2)查找匹配项,以及(3)对于每个匹配项,在原始 PDF 中文本的位置周围绘制一个可点击的框。我最接近的是 PyPDF2 的 addLink(),但这会在 PDF 中添加 internal 链接,而不是指向外部 URL 的链接。 可以,但是非常复杂。需要实现大量代码。 @Kurt 是的,这就是我要说的。请参阅我 1.5 年前的问题:***.com/questions/19414763/… 我会为你的彻底回答投票支持你,但我现在将悬赏开放,因为它没有回答问题。如果没有人提出可行的方法,我会给你赏金。 [我的评论回复了一条被删除的评论,内容如下:“您是说您知道 PDF 不包含文字字符串在您阅读之前我的答案?”]【参考方案3】:

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

【讨论】:

以上是关于在 PDF 中添加链接 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

PDF 中的 XSL-FO 超链接 - 打印关闭查看打开 - 天线之家

打开pdf,ppt ..等文件时,如何使用swift语言在Xcode中添加关闭或后退按钮?

如何将 HTML 和 CSS 添加到 PDF [关闭]

使用正则表达式自动向 PDF 文件添加注释 [关闭]

在 PDF 文件中使用 JavaScript 代码的文档 [关闭]

您如何在 wordpress 中动态创建 pdf? [关闭]