在日常的文档处理中,我们经常会遇到需要把一个体积较大的 PDF 拆成若干小文件的场景:比如只把合同中的某一页发给客户、把一份长篇报告按章节拆开归档,或者把扫描得到的超宽页面裁成多页以便打印。如果依赖手动操作或在线工具,不仅效率低,还可能带来文件外泄的风险。
借助 Python 中成熟的 PDF 处理库,我们可以在本地以编程方式完成各种拆分需求,而且方式非常灵活。本文将以 Spire.PDF 为例,介绍三种常用的拆分思路:按页拆分为单页文件、按指定页码范围提取页面,以及把一个超长页面重新分页为多页。
环境准备
在开始之前,需要先安装 Spire.PDF 库。可以通过 pip 直接安装:
bash
pip install Spire.PDF
安装完成后,在脚本顶部引入必要的命名空间即可。后续示例均使用 PdfDocument 作为操作 PDF 的核心对象。
python
from spire.pdf.common import *
from spire.pdf import *
将 PDF 拆分为单页文件
最常见的需求是把一个多页 PDF 每一页都单独保存成一个文件,例如把一份 10 页的资料拆成 10 个单页 PDF。PdfDocument 提供的 Split 方法专门为此设计,它会遍历文档的每一页,并按照指定的文件命名规则自动生成对应的独立文件,整个过程只需要一行调用。
python
from spire.pdf.common import *
from spire.pdf import *
input_file = "Sample.pdf"
# 加载待拆分的 PDF 文档
doc = PdfDocument()
doc.LoadFromFile(input_file)
# 按命名模板将每一页拆分为独立文件,{0} 会被替换为页码索引
pattern = "拆分pdf-{0}.pdf"
doc.Split(pattern)
doc.Close()

上面的代码中,Split 方法的参数是一个带占位符 {0} 的文件名模板,库会在拆分时自动用页码序号替換该占位符,最终得到 SplitDocument-0.pdf、SplitDocument-1.pdf 这样命名的一系列单页文件。这种方式适合需要"整本拆散"的场景,代码量最少,也最容易理解。
按指定页面范围拆分文件
有时我们并不想拆散整本文档,而只是想把其中的某几页(比如第 2 到第 4 页)提取出来生成一个新的 PDF。这时可以借助 PdfDocument.Pages.Add 在新文档中按原页尺寸新建页面,再通过 CreateTemplate().Draw() 把源页的内容完整绘制过去,从而精确控制到底抽取哪些页。
python
from spire.pdf.common import *
from spire.pdf import *
input_file = "/Sample.pdf"
output_file = "/按范围拆分.pdf"
# 加载源 PDF 并创建一个新的空 PDF 文档
old_pdf = PdfDocument()
old_pdf.LoadFromFile(input_file)
new_pdf = PdfDocument()
# 只抽取索引为 1 和 2 的页面(即原文档的第 2、3 页)
for i in range(1, 3):
# 按源页面尺寸新建一页,边距设为 0 以保留原始版式
page = new_pdf.Pages.Add(old_pdf.Pages[i].Size, PdfMargins(0.0))
# 将源页面内容以模板形式绘制到新页面上
old_pdf.Pages[i].CreateTemplate().Draw(page, PointF(0.0, 0.0))
new_pdf.SaveToFile(output_file)
new_pdf.Close()
old_pdf.Close()

这里的关键点在于 PdfMargins(0.0) 和 PointF(0.0, 0.0):前者保证新页面没有额外的页边距偏移,后者把源页模板的左上角对齐绘制到新页面的原点,从而避免内容被意外缩放或留白。通过调整 range 的起止值,就能灵活抽取任意连续的页码区间。
将单个大页面拆分为多页
还有一种特殊但常见的情形:源 PDF 的某一页本身非常高(例如长图截图、横向折叠的扫描件),缩放后难以阅读或打印。此时可以把这一页重新按高度"切"成多页。PdfTextLayout 的 Break 与 Layout 属性配合模板绘制,可以让库自动按新页面高度分页,把超长内容顺次排到后续页面中。
python
from spire.pdf.common import *
from spire.pdf import *
input_file = "/Sample.pdf"
output_file = "/分割单页.pdf"
doc = PdfDocument()
doc.LoadFromFile(input_file)
# 取出需要重新分页的那一页
page = doc.Pages[0]
new_pdf = PdfDocument()
# 移除新文档的页边距,使内容铺满页面
new_pdf.PageSettings.Margins.All = 0.0
# 新页面宽度与原页一致,高度减半,相当于一页切为两页
new_pdf.PageSettings.Width = page.Size.Width
new_pdf.PageSettings.Height = page.Size.Height / float(2)
new_page = new_pdf.Pages.Add()
# 设置排版规则:超出一页高度时自动换行到下一页
layout = PdfTextLayout()
layout.Break = PdfLayoutBreakType.FitPage
layout.Layout = PdfLayoutType.Paginate
# 将源页模板按上述排版规则绘制到新文档
page.CreateTemplate().Draw(new_page, PointF(0.0, 0.0), layout)
new_pdf.SaveToFile(output_file)
new_pdf.Close()
doc.Close()

需要留意的是,这种"切页"本质上是通过重新排版实现的:当源页内容能够自适应流式布局时(如纯文本或文本型扫描件),分页效果最理想;如果页面主要是位图图像,库会尽量按比例裁切,但效果取决于原始内容的构成。把 page.Size.Height 除以几,就能大致控制切成多少份。
实用技巧
掌握了以上三种拆分方式后,还可以结合实际场景做一些扩展,让拆分流程更顺手。
批量拆分多个 PDF 文件
如果需要拆分某个文件夹下的所有 PDF,可以结合 os 模块遍历目录,对每一个文件套用前面的拆分逻辑。下面的示例把文件夹里的每个 PDF 都按单页拆分:
python
import os
from spire.pdf.common import *
from spire.pdf import *
folder = "./pdfs"
for name in os.listdir(folder):
if not name.lower().endswith(".pdf"):
continue
doc = PdfDocument()
doc.LoadFromFile(os.path.join(folder, name))
# 用原文件名作为前缀,避免不同文件拆分出的页面重名
doc.Split(os.path.join(folder, "split", f"{os.path.splitext(name)[0]}-{{0}}.pdf"))
doc.Close()
拆分后保留页面顺序与命名
Split 方法生成文件名时使用的 {0} 是零基索引(第一页对应 0),如果希望输出从 1 开始编号,可以在拆分后用 os.rename 做一轮重命名。另外,无论是按范围抽取还是切页,源文档中的链接、注释等元素都会随页面内容一并被绘制到新文档中,因此拆分后通常无需额外处理这些对象。
小结
本文介绍了使用 Python 拆分 PDF 的三类典型做法:用 Split 方法快速把整本文档拆成单页文件、用 Pages.Add 加 CreateTemplate().Draw() 精确抽取指定页码范围、以及用 PdfTextLayout 把超长单页重新分页为多页。它们覆盖了从"整本拆散"到"按需抽取"再到"重新排版分页"的不同粒度需求。
在实际项目中,你可以根据拆分的目的选择合适的方式,也可以把上述思路组合使用,例如先按页码范围抽取关键章节,再对其中超长的页面做重新分页。配合 os、路径处理等标准库,还能轻松把拆分流程扩展到批量自动化场景。