如何使用PyPDF2合并PDF页面
有没有人用Python库PyPDF2合并两个PDF页面的经验?我尝试使用page1.mergePage(page2)
,结果是页面2覆盖在页面1上。请问怎么才能把页面2添加到页面1的底部呢?
5 个回答
pdfrw这个库可以做到这一点。在它的示例文件夹里,有一个4up的例子,能把4个输入页面放在每个输出页面上,还有一个小册子的例子,可以把8.5x11的输入变成11x17的输出。声明一下——我是pdfrw的作者。
我这样做了:
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的解决方案更好,但我还没试过。
如果这两个PDF文件不在你的电脑上,而是通常通过网址访问或下载的(比如 http://foo/bar.pdf 和 http://bar/foo.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())
在我搜索关于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等)不会被改变。参数页面的内容流会被添加到这一页的内容流末尾,也就是说它会在这一页的内容上面绘制。
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()