如何使用borb在Python中分割和合并PDF文档

935 阅读5分钟

简介

可移植文档格式并不是一种 WYSIWYG格式。它被开发成与平台无关,独立于底层操作系统和渲染引擎。

为了实现这一点,PDF的构造是通过更像编程语言的东西进行交互,并依靠一系列的指令和操作来实现结果。事实上,PDF是基于一种脚本语言--PostScript,它是第一个独立于设备的页面描述语言

在本指南中,我们将使用 borb- 一个专门用于阅读、操作和生成 PDF 文档的 Python 库。它提供了一个低级别的模型(如果你选择使用精确的坐标和布局,允许你访问这些)和一个高级别的模型(你可以将边距、位置等的精确计算委托给一个布局管理器)。

在本指南中,我们将看看如何使用borb在Python中分割和合并PDF文档,我们还将看看如何在PDF文档中旋转页面。

分割和合并PDF文档是许多应用场合的基础。

  • 处理一张发票(你不需要条款和条件,所以你可以删除这些页面)
  • 为文件(测试报告、发票、宣传材料)添加一封封面信
  • 汇总来自不同来源的测试结果
  • 等等

安装borb

borb可以从GitHub上的源代码下载,或通过pip

$ pip install borb

使用borb分割PDF

为了证明这一点,你需要一个有几页的PDF,
我们先用borb 创建这样一个PDF。这一步是可选的,你当然可以简单地使用你身边的一个PDF来代替。

from borb.pdf.canvas.color.color import HexColor
from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout
from borb.pdf.canvas.layout.page_layout.page_layout import PageLayout
from borb.pdf.canvas.layout.text.paragraph import Paragraph
from borb.pdf.document import Document
from borb.pdf.page.page import Page
from borb.pdf.pdf import PDF
from decimal import Decimal

def create_document(heading_color: HexColor = HexColor("0b3954"), 
                    text_color: HexColor = HexColor("de6449"),
                    file_name: str = "output.pdf"):

    d: Document = Document()

    N: int = 10
    for i in range(0, N):
    
        # Create a new Page, and append it to the Document
        p: Page = Page()
        d.append_page(p)
        
        # Set the PageLayout of the new Page
        l: PageLayout = SingleColumnLayout(p)
        
        # Add the paragraph to identify the Page
        l.add(Paragraph("Page %d of %d" % (i+1, N),
                        font_color=heading_color,
                        font_size=Decimal(24)))
                        
        # Add a Paragraph of dummy text                        
        l.add(Paragraph("""
                        Lorem Ipsum is simply dummy text of the printing and typesetting industry. 
                        Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, 
                        when an unknown printer took a galley of type and scrambled it to make a type specimen book. 
                        It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. 
                        It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, 
                        and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
                        """,
                        font_color=text_color))
    
    # Persist the Document to disk
    with open(file_name, "wb") as pdf_out_handle:
        PDF.dumps(pdf_out_handle, d)

这个示例代码生成了一个由10页组成的PDF文档。

  • 每页以 "10页中的第x页 "开始。这将使我们以后更容易识别这些页面。
  • 每页包含1段文字。

在 Python 中分割 PDF 文档

现在我们来分割这个 PDF。我们先把它一分为二,前半部分包含前5页,后半部分包含其余的页面。

def split_half_half():

  # Read PDF
  with open("output.pdf", "rb") as pdf_file_handle:
    input_pdf = PDF.loads(pdf_file_handle)

  # Create two empty PDFs to hold each half of the split
  output_pdf_001 = Document()
  output_pdf_002 = Document()

  # Split
  for i in range(0, 10):
    if i < 5:
      output_pdf_001.append_page(input_pdf.get_page(i))
    else:
      output_pdf_002.append_page(input_pdf.get_page(i))

  # Write PDF
  with open("output_001.pdf", "wb") as pdf_out_handle:
    PDF.dumps(pdf_out_handle, output_pdf_001)

  # Write PDF
  with open("output_002.pdf", "wb") as pdf_out_handle:
    PDF.dumps(pdf_out_handle, output_pdf_002)

我们把前5页提取到一个新的Document ,把后面的5页提取到第二个新的Document ,有效地把原来的一个实体分割成两个小实体。

这一点通过get_page() 方法变得很容易,因为它的返回类型可以直接用于与append_page()

你可以检查产生的PDF文件,以验证代码是否按预期运行。

splitting a pdf document in python

spllitting a pdf document in python

第一个文件在第5页结束,而第二个文件在第6页开始。

我们也可以根据其他的标准来分割!在下一个例子中,我们将通过把所有奇数页放在一个PDF中,而把偶数页放在另一个PDF中来分割PDF。

def split_even_odd():

  # Read PDF
  with open("output.pdf", "rb") as pdf_file_handle:
    input_pdf = PDF.loads(pdf_file_handle)
  
  # Rreate two empty PDFs to hold each half of the split
  output_pdf_001 = Document()
  output_pdf_002 = Document()

  # Split
  for i in range(0, 10):
    if i % 2 == 0:
      output_pdf_001.append_page(input_pdf.get_page(i))
    else:
      output_pdf_002.append_page(input_pdf.get_page(i))

  # Write PDF
  with open("output_001.pdf", "wb") as pdf_out_handle:
    PDF.dumps(pdf_out_handle, output_pdf_001)

  # Write PDF
  with open("output_002.pdf", "wb") as pdf_out_handle:
    PDF.dumps(pdf_out_handle, output_pdf_002)

你可以验证产生的PDF文件是否代表了上述的分割方式。

split pdf on odd pages

split pdf on odd pages

用 Python 合并 PDF 文档

为了完成接下来的例子,我们需要两个PDF。如果你还没有,让我们用前面的代码来生成它们。

create_document(HexColor("247B7B"), HexColor("78CDD7"), "output_001.pdf")
create_document(file_name="output_002.pdf")

用于分割的直觉与合并非常相似--尽管,我们可以将整个文档添加到其他文档中,而不仅仅是页面。虽然,有时你可能想在将一个文件与另一个文件合并之前将其分割(切掉最后一页)。

我们可以将它们完全合并(连接两个PDF),但我们也可以只将第一个PDF的一些页面添加到第二个PDF中,如果我们喜欢这种方式的话--像之前那样使用append_page()

让我们从完全串联它们开始。

def concatenate_two_documents():

  # Read first PDF
  with open("output_001.pdf", "rb") as pdf_file_handle:
    input_pdf_001 = PDF.loads(pdf_file_handle)
  
  # Read second PDF
  with open("output_002.pdf", "rb") as pdf_file_handle:
    input_pdf_002 = PDF.loads(pdf_file_handle)
  
  # Build new PDF by concatenating two inputs
  output_document = Document()
  output_document.append_document(input_pdf_001)
  output_document.append_document(input_pdf_002)
  
  # Write PDF
  with open("output.pdf", "wb") as pdf_out_handle:
    PDF.dumps(pdf_out_handle, output_document)

这段代码的结果应该是:

merging pdf documents in python with borb

在 Python 中旋转 PDF 文档的页面

PDF 文档中的一个页面可以被旋转 90 度的任何倍数。这种操作允许你在横向和纵向模式之间轻松切换。

在下一个例子中,你将从我们先前创建的一个输入 PDF 中旋转一个页面。

def rotate_first_page():
  # Read PDF
  with open("output_001.pdf", "rb") as pdf_file_handle:
    input_pdf_001 = PDF.loads(pdf_file_handle)

  # Rotate page
  input_pdf_001.get_page(0).rotate_left()  
  
  # Write PDF to disk
  with open("output.pdf", "wb") as pdf_out_handle:
    PDF.dumps(pdf_out_handle, input_pdf_001)

结果PDF看起来是这样的:

rotating pages of pdf documents in python

结论

在本指南中,我们已经看了如何合并和分割PDF文件。我们还通过旋转一些页面来修改一个现有的PDF。