如何使用PyPDF2添加PDF页面

15

有没有人使用Python库PyPDF2合并两个PDF文件页面的经验。当我尝试page1.mergePage(page2)时,结果是page2叠加在page1上面。如何使其将page2添加到page1底部?


作者可能正在寻找类似这样的东西:http://www.pdfdu.com/pdf-pages-merge.aspx - S.A.
5个回答

31

当我在搜索Python PDF合并方案时,我注意到有一个关于合并和附加的普遍误解。

大多数人称追加操作为合并,但实际上这并非如此。您在问题描述中真正需要使用的是 mergePage 方法,它应该被称为 applyPageOnTopOfAnother,但那有点长。您所寻找的是将两个文件/页面附加到一个新文件中。

PDF文件附加

使用 PdfFileMerger 类及其append方法

merge()方法相同,但假设您要将所有页面连接到文件末尾而不是指定位置。

以下是从pypdf 将多个pdf文件合并成一个pdf中摘取的一种方法:

from PyPDF2 import PdfFileMerger, PdfFileReader

# ...

merger = PdfFileMerger()

merger.append(PdfFileReader(file(filename1, 'rb')))
merger.append(PdfFileReader(file(filename2, 'rb')))

merger.write("document-output.pdf")

追加特定的PDF页面

要追加不同PDF文件的特定页面,请使用PdfFileWriter类和addPage方法

向此PDF文件添加页面。该页面通常来自PdfFileReader实例。

file1 = PdfFileReader(file(filename1, "rb"))
file2 = PdfFileReader(file(filename2, "rb"))

output = PdfFileWriter()

output.addPage(file1.getPage(specificPageIndex))
output.addPage(file2.getPage(specificPageIndex))

outputStream = file("document-output.pdf", "wb")
output.write(outputStream)
outputStream.close()

将两个页面合并为一个页面

使用mergePage函数。

将两个页面的内容流合并成一个。保留两个页面的资源引用(如字体)。此页面的mediabox/cropbox等不会被改变。参数page的内容流将被添加到此页面的内容流末尾,即它将在此页面之后或“顶部”绘制。

file1 = PdfFileReader(file(filename1, "rb"))
file2 = PdfFileReader(file(filename2, "rb"))

output = PdfFileWriter()

page = file1.getPage(specificPageIndex)
page.mergePage(file2.getPage(specificPageIndex))

output.addPage(page)

outputStream = file("document-output.pdf", "wb")
output.write(outputStream)
outputStream.close()

2
不好意思,你误会了我的意思。我需要的是将两个页面合并成一个,一个在另一个下面。 - Valentin Melnikov
你应该在问题中澄清这一点。你的意思是,比如第一页在上半部分,第二页在下半部分吗? - Emile Bergeron
@ValentinMelnikov 仍然没有合并,而是将两个页面的内容附加到一个新页面上。 - Emile Bergeron
2
但是这个答案对我非常有用 :)(我的任务是将前景和背景组合起来并获得输出) - xwild
1
“Append”在谈论PDF时具有特殊的含义。由于PDF允许通过在文档末尾编写新版本的树来改变文档的内容和呈现方式,因此只需附加字节即可。当尝试通过增量更新保留文档的过去版本时,这一点尤为重要。请参阅Adobe的此文档“PDF中的数字签名”(https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf)中的图5。 - yucer
显示剩余3条评论

4
如果在您的本地计算机上不存在这两个PDF文件,而是通过URL正常访问/下载(即http://foo/bar.pdfhttp://bar/foo.pdf),我们可以从远程位置获取这两个PDF文件,并在内存中一次性合并它们。
这样就省去了先下载PDF文件的步骤,并且使解决方案不再局限于简单情况下的两个已存在于磁盘上的PDF文件。特别地,它将解决方案推广到任何HTTP可访问的PDF文件。
以下是示例:
    from PyPDF2 import PdfFileMerger, PdfFileReader

    pdf_content_1 = requests.get('http://foo/bar.pdf').content
    pdf_content_2 = requests.get('http://bar/foo.pdf').content

    # Write to in-memory file-like buffers        
    pdf_buffer_1 = StringIO.StringIO().write(pdf_content_1)
    pdf_buffer_2 = StringIO.StringIO().write(pdf_content_2)
    pdf_merged_buffer = StringIO.StringIO()

    merger = PdfFileMerger()
    merger.append(PdfFileReader(pdf_buffer_1))
    merger.append(PdfFileReader(pdf_buffer_2))
    merger.write(pdf_merged_buffer)

    # Option 1:
    # Return the content of the buffer in an HTTP response (Flask example below)
    response = make_response(pdf_merged_buffer.getvalue())
    # Set headers so web-browser knows to render results as PDF
    response.headers['Content-Type'] = 'application/pdf'
    response.headers['Content-Disposition'] = \ 
        'attachment; filename=%s.pdf' % 'Merged PDF'
    return response 
    # Option 2: Write to disk
    with open("merged_pdf.pdf", "w") as fp:
        fp.write(pdf_merged_buffer.getvalue())

这与手头的问题没有任何新的关联,其余内容超出了此处的范围。 - Emile Bergeron
是的,这里的答案是解决比OP更具体的问题的特定方法。它仍然作为OP的替代方法相关。如果您认为此答案没有增加价值,请投反对票或标记,而不是留下带有个人观点的评论。 - The Aelfinn
这个问题是关于如何使用Python合并/追加PDF文件的。从互联网下载文件与此无关。这也不是一种替代方法,因为您仍然使用相同的“PdfFileMerger”技术。 - Emile Bergeron
这个程序使用相同的方法(PdfFileMerger),但不假设两个PDF文件都在本地磁盘上可用,而是推广到使用远程PDF文件。再次提醒,请在StackOverflow上遇到问题时,不要发表带有个人观点的评论,而是请按下投票或标记按钮。 - The Aelfinn
@TheAelfinn 当我尝试你的方法时,总是会出现AttributeError: 'int' object has no attribute 'seek'错误,其中包括merger.append(PdfFileReader(pdf_buffer_1)) - Mazze

3

我是这样做的:

reader = PyPDF2.PdfFileReader(open("input.pdf",'rb'))

NUM_OF_PAGES = reader.getNumPages()

page0 = reader.getPage(0)
h = page0.mediaBox.getHeight()
w = page0.mediaBox.getWidth()

newpdf_page = PyPDF2.pdf.PageObject.createBlankPage(None, w, h*NUM_OF_PAGES)
for i in range(NUM_OF_PAGES):
    next_page = reader.getPage(i)
    newpdf_page.mergeScaledTranslatedPage(next_page, 1, 0, h*(NUM_OF_PAGES-i-1))

writer = PdfFileWriter()
writer.addPage(newpdf_page)

with open('output.pdf', 'wb') as f:
    writer.write(f)

当每个页面的高度和宽度相同时,此方法可行。否则,它需要进行一些修改。

也许Emile Bergeron的解决方案更好。没有尝试过。


2

pdfrw库可以实现此功能。在示例目录中有一个4up示例,将4个输入页面放置在每个输出页面上,还有一个小册子示例,将8.5x11的输入创建为11x17的输出。免责声明-我是pdfrw的作者。


-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接