在处理扫描件、截图导出的 PDF 或带有大量留白的报告时,我们常常只关心其中的某一部分内容:比如一页里右下角的图表、被白边包围的正文,或者某一栏表格。直接保留整页不仅浪费版面,也会让后续的阅读、打印和归档变得低效。
"裁剪"的本质,是把页面中不需要的区域切掉,只保留我们关注的矩形范围。借助 Spire.PDF,我们可以通过"在新页面上重绘源页内容并做偏移"的方式,精确地按任意矩形裁剪页面,也可以快速裁掉四周的空白边距。下面以具体示例说明几种常用做法。
环境准备
开始之前,先通过 pip 安装 Spire.PDF:
bash
pip install Spire.PDF
随后在脚本中引入所需的命名空间。后续所有示例都围绕 PdfDocument 与 PdfPageBase 展开。
python
from spire.pdf.common import *
from spire.pdf import *
按指定矩形区域裁剪
最通用的需求是:给定一个矩形(左上角坐标加宽高),把源页中落在这个矩形内的部分单独保存成一个新页面。实现思路是新建一个与目标矩形等大的新页面,再用 DrawTemplate 把源页内容按矩形原点向左上偏移绘制,这样矩形区域就会恰好对齐到新页面的左上角,矩形以外的部分被自然裁掉。
python
from spire.pdf.common import *
from spire.pdf import *
input_file = "/示例.pdf"
output_file = "/裁剪pdf.pdf"
# 创建一个 PdfDocument 对象并加载 PDF 文件
doc = PdfDocument()
doc.LoadFromFile(input_file)
# 取第一页作为裁剪对象
page = doc.Pages[0]
# 定义裁剪区域:左上角坐标与宽高,单位均为"点"(1 英寸 = 72 点)
crop_x, crop_y = 50.0, 80.0
crop_w, crop_h = 400.0, 500.0
# 新建一个与目标裁剪尺寸一致、无边距的页面
new_doc = PdfDocument()
new_page = new_doc.Pages.Add(SizeF(crop_w, crop_h), PdfMargins(0.0))
# 把源页模板按裁剪原点偏移绘制,使目标区域对齐到新页面左上角
new_page.Canvas.DrawTemplate(page.CreateTemplate(), PointF(-crop_x, -crop_y))
# 保存修改后的 PDF 文件
new_doc.SaveToFile(output_file)
new_doc.Close()
doc.Close()

这里有几个值得注意的点。SizeF 用于描述新页面的尺寸,必须和裁剪矩形保持一致,否则内容会被缩放或留白;PdfMargins(0.0) 确保新页面没有额外边距;而 PointF(-crop_x, -crop_y) 中的负号很关键------它把源页整体向左上平移,让 (crop_x, crop_y) 这个点正好落到新页面的 (0, 0) 处。只要调整这四个数值,就能裁剪出页面上任意位置的子区域。
裁剪掉四周的空白边距
很多 PDF 的页面四周都自带较大的白边,正文只占中间一部分。如果每一页的边距大致均匀,我们可以利用文档的 PageSettings.Margins 直接算出内容区尺寸,再把内容按边距偏移重绘,从而一次性裁掉所有页面的白边。
python
from spire.pdf.common import *
from spire.pdf import *
input_file = "/示例.pdf"
output_file = "移除页边距.pdf"
# 创建 PdfDocument 对象并加载 PDF 文件
doc = PdfDocument()
doc.LoadFromFile(input_file)
# 获取页边距并创建新的 PdfDocument 对象
new_doc = PdfDocument()
margins = doc.PageSettings.Margins
left, right = margins.Left, margins.Right
top, bottom = margins.Top, margins.Bottom
for i in range(doc.Pages.Count):
page = doc.Pages.get_Item(i)
# 新页面尺寸 = 原尺寸减去四周边距
w = page.Size.Width - left - right
h = page.Size.Height - top - bottom
new_page = new_doc.Pages.Add(SizeF(w, h), PdfMargins(0.0))
# 向左上偏移绘制,从而裁掉边距区域
new_page.Canvas.DrawTemplate(page.CreateTemplate(), PointF(-left, -top))
# 保存修改后的 PDF 文件
new_doc.SaveToFile(output_file)
new_doc.Close()
doc.Close()

这种方法的核心在于 page.Size 拿到的是包含边距的整页尺寸,而 doc.PageSettings.Margins 描述的是白边的厚度。两者相减得到真正的内容区,再用 PointF(-left, -top) 把内容重新对齐到原点,就完成了"去白边"式的裁剪。它对批量处理多页文档尤其方便,因为循环里每一页都套用同样的逻辑。
读取页面尺寸与裁剪框以确认结果
裁剪前后,我们有时还需要知道页面到底有多大、当前可见区域(裁剪框)落在什么位置。PDF 的每一页都带有 MediaBox(物理尺寸)和 CropBox(当前可见区域)等边界框,PdfPageBase 把它们作为可读属性暴露出来,可以用来核对裁剪是否生效,也能作为下一次裁剪的输入。
python
from spire.pdf.common import *
from spire.pdf import *
doc = PdfDocument()
doc.LoadFromFile("Sample.pdf")
page = doc.Pages[0]
# MediaBox 是页面物理尺寸,CropBox 是当前可见(裁剪后)区域
print("MediaBox:", page.MediaBox.Width, page.MediaBox.Height)
print("CropBox:", page.CropBox.Width, page.CropBox.Height,
page.CropBox.X, page.CropBox.Y)
print("实际尺寸:", page.ActualSize.Width, page.ActualSize.Height)
doc.Close()
通过对比裁剪前后的 MediaBox 与 CropBox(或重绘后新页面的 ActualSize),可以直观地验证页面确实被缩小到了目标区域。如果源文档本身已经设置了 CropBox,它的 (X, Y) 还能直接当作裁剪矩形的起点来用,省去手动测量坐标的步骤。
实用技巧
掌握了裁剪的基本手法后,还可以结合实际场景做进一步扩展。
批量裁剪整个文件夹
把上面的"按矩形裁剪"逻辑包进一个遍历目录的循环,就能对某个文件夹下的所有 PDF 统一裁剪。下面示例用 os 模块批量处理,并为每个输出文件加上前缀避免重名:
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))
page = doc.Pages[0]
new_doc = PdfDocument()
new_page = new_doc.Pages.Add(SizeF(400.0, 500.0), PdfMargins(0.0))
new_page.Canvas.DrawTemplate(page.CreateTemplate(), PointF(-50.0, -80.0))
out = os.path.join(folder, "cropped", f"cropped-{name}")
new_doc.SaveToFile(out)
new_doc.Close()
doc.Close()
用厘米指定裁剪区域
前面示例的坐标都以"点"为单位,阅读和调试不够直观。可以借助 PdfUnitConvertor 把厘米换算成点,让裁剪矩形以更熟悉的尺寸单位来表达:
python
from spire.pdf.common import *
from spire.pdf import *
cvtr = PdfUnitConvertor()
# 把 2 厘米换算为点
pt = cvtr.ConvertUnits(2.0, PdfGraphicsUnit.Centimeter, PdfGraphicsUnit.Point)
print("2 厘米 =", pt, "点")
这样在定义 crop_x、crop_y、crop_w、crop_h 时,先统一用厘米描述,再用 ConvertUnits 转成点传入 SizeF 和 PointF,代码可读性会更好,也更不容易算错比例。
小结
本文介绍了使用 Python 裁剪 PDF 页面的两种主要方式:按任意矩形区域精确裁剪,以及裁掉四周统一白边。两者的共同原理都是"新建一个目标尺寸的新页面,再用 DrawTemplate 把源页内容按偏移量重绘",区别在于矩形坐标的来源------前者由我们手动指定,后者从 PageSettings.Margins 自动推导。
再配合 CropBox/MediaBox 的读取做结果核对,以及 os、PdfUnitConvertor 等标准工具做批量与单位换算,裁剪流程就能轻松扩展到日常自动化场景。如果你的目标是"隐藏"而非"删除"页外内容,也可以直接调整页面的 CropBox 来定义可见区域,按需选择即可。