news 2026/6/26 10:24:10

Day 44:【99天精通Python】操作 PDF (PyPDF2) - 文档处理的屠龙刀

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day 44:【99天精通Python】操作 PDF (PyPDF2) - 文档处理的屠龙刀

Day 44:【99天精通Python】操作 PDF (PyPDF2) - 文档处理的屠龙刀

前言

欢迎来到第44天!

在办公自动化领域,除了 Word 和 Excel,PDF是最常见的文件格式。它的特点是"所见即所得",在任何设备上打开格式都不会乱。但这也导致它很难编辑

你是否遇到过这些需求?

  • 把 10 个 PDF 文件合并成一个。
  • 把一个几百页的 PDF拆分成单独的章节。
  • 从 PDF 中提取文本内容(虽然效果不一定完美)。
  • 给 PDF 加密或添加水印。

Python 提供了多个 PDF 处理库,其中最流行、最轻量级的是PyPDF2。今天我们就来掌握这把处理 PDF 的屠龙刀。

本节内容:

  • 安装 PyPDF2
  • 读取 PDF 信息(页数、元数据)
  • 提取文本内容
  • 拆分 PDF 页面
  • 合并多个 PDF
  • 加密与解密 PDF

一、安装 PyPDF2

注意:PyPDF2 在 3.0 版本后 API 有较大变动(如PdfFileReader改名为PdfReader)。本教程使用最新的 3.x 版本。

pipinstallPyPDF2

二、读取 PDF 信息

我们需要一个测试文件sample.pdf

fromPyPDF2importPdfReader# 1. 打开 PDFreader=PdfReader("sample.pdf")# 2. 获取总页数print(f"总页数:{len(reader.pages)}")# 3. 获取元数据 (作者、标题等)meta=reader.metadataprint(f"标题:{meta.title}")print(f"作者:{meta.author}")

2.1 提取文本 (Extract Text)

# 获取第一页page=reader.pages[0]# 提取文本text=page.extract_text()print(text)

注意:PDF 的本质是排版指令,而不是文本流。如果 PDF 是扫描件(全是图片),或者使用了特殊编码的字体,提取出来的可能是乱码或空字符串。对于扫描件,需要使用 OCR 技术(如pytesseract),这超出了 PyPDF2 的能力范围。


三、拆分 PDF (Split)

假设我们要把每一页单独保存为一个 PDF 文件。

fromPyPDF2importPdfReader,PdfWriter reader=PdfReader("sample.pdf")fori,pageinenumerate(reader.pages):# 创建一个写入器writer=PdfWriter()# 将当前页添加到写入器writer.add_page(page)# 保存文件filename=f"page_{i+1}.pdf"withopen(filename,"wb")asf:writer.write(f)print(f"已保存:{filename}")

四、合并 PDF (Merge)

把多个 PDF 合并成一个。PyPDF2 提供了更高级的PdfMerger类,比手动add_page更方便。

fromPyPDF2importPdfMergerimportos# 获取所有要合并的文件files=["report_part1.pdf","report_part2.pdf","report_part3.pdf"]merger=PdfMerger()forpdfinfiles:# append 可以直接追加文件merger.append(pdf)# 保存合并结果merger.write("report_final.pdf")merger.close()print("合并完成!")

进阶:插入到指定位置

# 把 part2 插在 part1 的第 2 页之后merger.append("part1.pdf")merger.merge(2,"part2.pdf")# 在索引2的位置插入

五、加密与解密

5.1 给 PDF 加密码

fromPyPDF2importPdfReader,PdfWriter reader=PdfReader("sample.pdf")writer=PdfWriter()# 将所有页复制到 writerforpageinreader.pages:writer.add_page(page)# 设置密码writer.encrypt("123456")# 保存withopen("locked.pdf","wb")asf:writer.write(f)

5.2 读取加密的 PDF

如果直接读取加密文件,会抛出错误或获取不到内容。

reader=PdfReader("locked.pdf")ifreader.is_encrypted:print("文件已加密,尝试解密...")# 尝试解密 (返回 True/False)ifreader.decrypt("123456"):print(f"解密成功,页数:{len(reader.pages)}")else:print("密码错误!")

六、实战练习:PDF 工具箱

编写一个命令行工具,根据用户输入实现合并或拆分功能。

importosfromPyPDF2importPdfReader,PdfWriter,PdfMergerdefsplit_pdf(filename):"""拆分 PDF 的每一页"""try:reader=PdfReader(filename)base_name=os.path.splitext(filename)[0]fori,pageinenumerate(reader.pages):writer=PdfWriter()writer.add_page(page)output=f"{base_name}_p{i+1}.pdf"withopen(output,"wb")asf:writer.write(f)print(f"拆分完成,共{len(reader.pages)}个文件。")exceptExceptionase:print(f"拆分失败:{e}")defmerge_pdfs(file_list,output_name="merged.pdf"):"""合并多个 PDF"""merger=PdfMerger()try:forpdfinfile_list:ifos.path.exists(pdf):merger.append(pdf)else:print(f"跳过不存在的文件:{pdf}")merger.write(output_name)print(f"合并完成:{output_name}")exceptExceptionase:print(f"合并失败:{e}")finally:merger.close()if__name__=="__main__":print("1. 拆分 PDF")print("2. 合并 PDF")choice=input("请选择: ")ifchoice=="1":path=input("请输入要拆分的 PDF 路径: ")split_pdf(path)elifchoice=="2":paths=input("请输入要合并的 PDF 路径 (用逗号分隔): ").split(",")# 去除空白paths=[p.strip()forpinpaths]merge_pdfs(paths)

七、常见问题

Q1:提取的文本是乱码?

这通常是因为 PDF 缺少字体映射表(CMap),或者是图片型 PDF。
解决方案:PyPDF2 搞不定。尝试pdfplumber库(提取效果更好),或者pytesseract(OCR 识别)。

Q2:合并后文件体积变大?

PDF 内部可能包含重复的字体或图片资源。合并时 PyPDF2 有时无法完美去重。可以使用 Acrobat Pro 进行优化,或者尝试pikepdf库。

Q3:如何旋转页面?

# 顺时针旋转 90 度page.rotate(90)

八、小结

PyPDF2

读取 PdfReader

写入 PdfWriter

合并 PdfMerger

len(pages) 页数

pages[0].extract_text() 文本

decrypt() 解密

add_page() 添加页

encrypt() 加密

write() 保存

append() 追加文件

merge() 插入文件

关键要点

  1. 拆分Reader读,Writer写。
  2. 合并:直接用PdfMerger最快。
  3. 局限性:对文本提取支持有限,不适合处理扫描件。

九、课后作业

  1. 奇偶拆分:编写程序,将一个 PDF 拆分成两个文件:odd.pdf(包含第 1,3,5… 页)和even.pdf(包含第 2,4,6… 页)。
  2. 页面旋转矫正:读取一个 PDF,将所有页面旋转 180 度(倒立),并保存为新文件。
  3. 水印添加 (挑战):结合 Day 42 (Pillow) 和 PyPDF2。先用 Pillow 生成一张透明的水印图片,转为 PDF,然后将水印 PDF 与目标 PDF 的每一页进行合并(Overlay)。(提示:page.merge_page())。

下节预告

Day 45:进阶篇总结与展望- 我们的进阶之旅即将画上句号。明天我们将复盘进阶篇的核心知识体系,并为接下来的重头戏——实战篇 (数据分析与Web开发)做好准备!


系列导航

  • 上一篇:Day 43 - 发送邮件smtplib
  • 下一篇:Day 45 - 进阶篇总结与展望(待更新)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/25 17:03:04

fft npainting lama图像修复系统ARM架构:树莓派等设备可行性测试

fft npainting lama图像修复系统ARM架构:树莓派等设备可行性测试 1. 引言 随着边缘计算和嵌入式AI应用的快速发展,将图像修复类深度学习模型部署到低功耗、低成本的ARM架构设备(如树莓派)上成为一项具有实际价值的技术探索。本文…

作者头像 李华
网站建设 2026/6/25 18:38:27

迎接充电基础设施“新规范”,如何用一套系统实现全网智能管理?

安科瑞刘鸿鹏172 一 ⑥⑨⑦② 一 5322摘要随着工业用电规模的持续扩大,中压配电系统在保障企业连续生产中的重要性日益凸显。开关柜作为工业配电系统的关键节点,其内部绝缘状态直接影响供电安全与运行可靠性。局部放电作为绝缘劣化的早期表现形式&#x…

作者头像 李华
网站建设 2026/6/25 18:34:28

OpenDataLab MinerU避坑指南:常见问题全解答

OpenDataLab MinerU避坑指南:常见问题全解答 1. 引言 在当前AI驱动的文档智能处理场景中,OpenDataLab/MinerU2.5-2509-1.2B 模型凭借其轻量级架构和专业化的文档理解能力,成为众多开发者与企业的首选工具。该模型基于 InternVL 架构&#x…

作者头像 李华
网站建设 2026/6/26 8:28:24

AMD Ryzen处理器调试终极指南:全面解锁硬件性能潜力

AMD Ryzen处理器调试终极指南:全面解锁硬件性能潜力 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitc…

作者头像 李华
网站建设 2026/6/26 8:32:01

Qwen3-32B极速体验:5分钟从注册到对话,不装环境

Qwen3-32B极速体验:5分钟从注册到对话,不装环境 你是不是也遇到过这样的情况:产品发布会马上就要开始了,领导突然说“加个AI互动环节”,技术同事却临时请假,整个团队陷入慌乱?别急——今天我要…

作者头像 李华
网站建设 2026/6/26 8:32:01

Legacy iOS Kit完全指南:让老款苹果设备重获新生的终极工具链

Legacy iOS Kit完全指南:让老款苹果设备重获新生的终极工具链 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to downgrade/restore, save SHSH blobs, and jailbreak legacy iOS devices 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit …

作者头像 李华