查看: 210|回复: 0

Python裁剪PDF页面实现按指定矩形区域与去除白边

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
在阅读或归档扫描件、截图类PDF时,页面四周的多余留白和不相关区域往往会影响效率。比如只想保留一页中的图表、表格或某一栏正文,此时可以通过“裁剪”方式切掉不需要的部分。使用Spire.PDF库,Python脚本可以实现按任意矩形范围精确裁剪,也能快速去除四周空白,适合批量处理日常文档。其核心原理并不复杂:新建一个和目标区域等大小的新页面,把源页面内容通过偏移重绘过去,最终只留下需要的内容。

环境准备

先通过pip安装Spire.PDF:
  1. pip install Spire.PDF
复制代码

然后在脚本中引入相关命名空间,后续所有操作都会围绕PdfDocument和PdfPageBase进行:
  1. from spire.pdf.common import *
  2. from spire.pdf import *
复制代码

按指定矩形区域裁剪

最常见需求是给定一个矩形(左上角坐标+宽度+高度),把源页面中该矩形内的内容保存到新页面。实现思路是创建一个与目标矩形尺寸完全相同的新页面,然后使用DrawTemplate绘制源页面模板,并传入负的偏移坐标,使目标区域的左上角恰好对齐新页面原点。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. input_file = "/示例.pdf"
  4. output_file = "/裁剪pdf.pdf"
  5. doc = PdfDocument()
  6. doc.LoadFromFile(input_file)
  7. page = doc.Pages[0]
  8. # 裁剪区域:左上角坐标 + 宽高,单位均为“点”(1英寸=72点)
  9. crop_x, crop_y = 50.0, 80.0
  10. crop_w, crop_h = 400.0, 500.0
  11. new_doc = PdfDocument()
  12. new_page = new_doc.Pages.Add(SizeF(crop_w, crop_h), PdfMargins(0.0))
  13. # 负偏移让源页面整体向左上移动,从而把指定区域放入新页面
  14. new_page.Canvas.DrawTemplate(page.CreateTemplate(), PointF(-crop_x, -crop_y))
  15. new_doc.SaveToFile(output_file)
  16. new_doc.Close()
  17. doc.Close()
复制代码

这里有几个关键细节:SizeF的参数必须与裁剪矩形保持一致,否则内容会被缩放或出现留白;PdfMargins(0.0)用于去掉新页面默认边距;PointF(-crop_x, -crop_y)的负号决定了裁剪位置的准确对齐。修改这四个数值,即可获得页面上任意位置的子区域。

裁剪掉四周空白边距

很多PDF页面自带较大白边,正文只占中间部分。如果各页边距均匀,可以通过PageSettings.Margins读取边距值,再按边距偏移重绘,一次处理所有页面。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. input_file = "/示例.pdf"
  4. output_file = "移除页边距.pdf"
  5. doc = PdfDocument()
  6. doc.LoadFromFile(input_file)
  7. new_doc = PdfDocument()
  8. margins = doc.PageSettings.Margins
  9. left, right = margins.Left, margins.Right
  10. top, bottom = margins.Top, margins.Bottom
  11. for i in range(doc.Pages.Count):
  12.     page = doc.Pages.get_Item(i)
  13.     # 新页面尺寸 = 原页面尺寸 - 四周边距
  14.     w = page.Size.Width - left - right
  15.     h = page.Size.Height - top - bottom
  16.     new_page = new_doc.Pages.Add(SizeF(w, h), PdfMargins(0.0))
  17.     # 向左上偏移绘制,去除白边
  18.     new_page.Canvas.DrawTemplate(page.CreateTemplate(), PointF(-left, -top))
  19. new_doc.SaveToFile(output_file)
  20. new_doc.Close()
  21. doc.Close()
复制代码

这种方法利用page.Size拿到包含边距的整页尺寸,doc.PageSettings.Margins则描述白边厚度,两者相减得到真正的内容区。再用PointF(-left, -top)将内容重新对齐到原点,就完成了去白边裁剪。循环遍历Pages集合时,每一页都会套用相同逻辑,尤其适合多页文档。

读取页面尺寸与裁剪框确认结果

裁剪前后往往需要确认页面物理尺寸和当前可见区域。PDF每页都带有MediaBox(物理尺寸)和CropBox(当前可见区域)等边界框,PdfPageBase将这些属性直接暴露出来,可用于核对裁剪是否生效,也可作为下一次裁剪的输入。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. doc = PdfDocument()
  4. doc.LoadFromFile("Sample.pdf")
  5. page = doc.Pages[0]
  6. print("MediaBox:", page.MediaBox.Width, page.MediaBox.Height)
  7. print("CropBox:", page.CropBox.Width, page.CropBox.Height,
  8.       page.CropBox.X, page.CropBox.Y)
  9. print("实际尺寸:", page.ActualSize.Width, page.ActualSize.Height)
  10. doc.Close()
复制代码

通过对比MediaBox与CropBox(或重绘后新页面的ActualSize),可以直观地确认页面是否已缩小到目标区域。如果源文档本身设置了CropBox,它的(X, Y)坐标可直接作为裁剪矩形的起点,省去手动测量坐标的步骤。

实用技巧:批量裁剪文件夹内所有PDF

把按矩形裁剪的逻辑放进目录遍历循环,即可批量处理某个文件夹下的所有PDF。下面示例使用os模块遍历文件,并为输出文件加上前缀避免重名。
  1. import os
  2. from spire.pdf.common import *
  3. from spire.pdf import *
  4. folder = "./pdfs"
  5. for name in os.listdir(folder):
  6.     if not name.lower().endswith(".pdf"):
  7.         continue
  8.     doc = PdfDocument()
  9.     doc.LoadFromFile(os.path.join(folder, name))
  10.     page = doc.Pages[0]
  11.     new_doc = PdfDocument()
  12.     new_page = new_doc.Pages.Add(SizeF(400.0, 500.0), PdfMargins(0.0))
  13.     new_page.Canvas.DrawTemplate(page.CreateTemplate(), PointF(-50.0, -80.0))
  14.     out = os.path.join(folder, "cropped", f"cropped-{name}")
  15.     new_doc.SaveToFile(out)
  16.     new_doc.Close()
  17.     doc.Close()
复制代码

注意使用该脚本前需先创建“cropped”输出目录,否则保存时会因路径不存在而失败。

用厘米指定裁剪区域

前面的坐标都以“点”为单位,不直观。借助PdfUnitConvertor可以将厘米换算成点,让裁剪矩形的描述更符合日常习惯。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. cvtr = PdfUnitConvertor()
  4. # 将2厘米换算为点
  5. pt = cvtr.ConvertUnits(2.0, PdfGraphicsUnit.Centimeter, PdfGraphicsUnit.Point)
  6. print("2 厘米 =", pt, "点")
复制代码

定义crop_x、crop_y、crop_w、crop_h时,先用厘米描述,再用ConvertUnits转换成点,传入SizeF和PointF。这样代码可读性更好,也不容易算错比例。

小结

本文介绍了Python下裁剪PDF页面的两种主要做法:按任意矩形区域精确裁剪,以及按边距自动去除白边。两者的共同原理都是“新建目标尺寸的新页面,用DrawTemplate按偏移量重绘源页面”,区别仅在于矩形坐标来源:前者手动指定,后者从PageSettings.Margins自动推导。结合MediaBox/CropBox读取、os目录遍历以及PdfUnitConvertor单位换算,可以轻松扩展到批量自动化场景。若只想“隐藏”而非“删除”页面外内容,也可以直接调整CropBox来定义可见区域,按需选择即可。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-2 13:05 , Processed in 0.020491 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部