我需要以编程方式分析和组合几个(数百个)PDF文档,并以专门的方式将页面链接在一起。每个PDF都包含链接所属的每个位置的文本,指示它应链接到的位置。我正在使用pdfminer
来提取链接所在的位置和文本;现在我只需要实际创建这些链接。
我做了一些研究并得出结论认为PyPDF2
可以做到这一点。无论如何,有一种看似简单的addLink
方法声称可以完成工作。我无法让它发挥作用。
from PyPDF2 import PdfFileWriter
from PyPDF2.pdf import RectangleObject
out = PdfFileWriter()
out.insertBlankPage(800, 1000)
out.insertBlankPage(800, 1000)
# rect = [400, 400, 600, 600] # This doesn't seem to work either
rect = RectangleObject([400, 400, 600, 600])
out.addLink(0, 1, rect) # link from first to second page
with open(r'C:\temp\test.pdf', 'wb') as outf:
out.write(outf)
上面的代码生成了一个漂亮的两页PDF,其中没有任何内容,至少据我所知。有没有人知道如何实现这一目标?或者至少表明我哪里出错了?
解决方案不必使用PyPDF2,只要该库是免费许可的。严格来说,Python甚至不是一个要求,但如果不将其他语言侵入到我当前的结构中,那将很好。
答案 0 :(得分:5)
这似乎是addLink
实现中的错误,或者该方法可能仅适用于较旧或不同的链接语法。无论如何,从问题中的示例代码检查输出PDF的结构揭示了这个小宝石:
6 0 obj
<<
/Dest [ 4 0 R /FitV 826 ]
/Type /Annot
/Rect RectangleObject([400, 400, 600, 600])
/Border [ 0 0 0 ]
/P IndirectObject(5, 0)
/Subtype /Link
>>
这有几个问题。最明显的是RectangleObject
和IndirectObject
是Python库的构造,不是有效的PDF结构。 /Dest
似乎也有一个我没有要求的神秘魔法参数。此外,/P
将是多余的(对包含此链接的页面的引用),即使它是以不将Python对象强制转换为PDF结构的方式实现的。简而言之,毫无疑问,这种联系已经破裂。
使用源消息来消除崩溃错误,结果是需要进行两次更改*才能使链接进入正常工作状态:从/Rect
更改NameObject
的内部表示转到ArrayObject
,并将/P
引用更改为指向页码,而不是实际对象。这些更改使示例代码生成有效输出:
6 0 obj
<<
/Dest [ 4 0 R /FitV ]
/Type /Annot
/Rect [ 400 400 600 600 ]
/Border [ 0 0 0 ]
/P 0
/Subtype /Link
>>
Etvoilà,链接在输出中完全按预期工作!我还从826
值中移除了魔术/Rect
,因为它可能不是合法参数,具体取决于缩放级别,并且它实际上不应该是硬编码的。
*在得出结论此修复程序按预期工作后,我确实认为将/Rect
保留为NameObject
并向其传递一个类似于输出的字符串(例如'[ 400 400 600 600 ]'
)也会奏效。这可能是为了获得最大的灵活性,但肯定是出乎意料的。
更新:我整理并提交了一个更完整的修补程序(后代link to the patch),因此上述问题都应该修复,从版本1.22