pypdf2读取失败主因是文件非标准pdf,如扫描件或word导出伪pdf;pymupdf更稳,支持加密、保留元数据及页面属性,且适合处理扫描pdf。

拆分PDF时为什么PyPDF2读取失败?
常见报错是 PdfReadError: Not a PDF file 或 UnicodeDecodeError,本质是文件非标准PDF(比如扫描件OCR后带加密、或由Word直接导出的伪PDF)。PyPDF2 对 PDF 版本和结构敏感,遇到加密、流压缩异常、交叉引用表损坏就直接抛错。
- 先用
pdfinfo(命令行)或fitz.open()(PyMuPDF)检查是否可读:fitz.open("file.pdf")能打开基本说明结构合法 - 若含密码,
PyPDF2.PdfReader需显式调用.decrypt("password");PyMuPDF则在open()时传参password="xxx" - 避免用
os.system("pdftk ...")这类外部工具——路径空格、中文路径、权限问题极易中断脚本
按页码范围拆分PDF:PyMuPDF比PyPDF2更稳
PyPDF2 拆分大文件(>100页)易内存溢出,且不保留书签、图层、表单字段;PyMuPDF(即 fitz)底层用 MuPDF,速度快、支持更多 PDF 特性,且 API 更直白。
- 拆单页:
doc[5]获取第6页(0-index),new_doc.insert_pdf(doc, from_page=5, to_page=5) - 拆连续页:
new_doc.insert_pdf(doc, from_page=10, to_page=19)—— 注意to_page是闭区间 - 批量拆成单页文件:循环中用
page = doc[n]; new_doc = fitz.open(); new_doc.insert_pdf(doc, from_page=n, to_page=n); new_doc.save(f"page_{n+1}.pdf")
合并PDF时如何保持原顺序且不丢元数据?
直接用 PyPDF2.PdfMerger.append() 会丢掉源文档的标题、作者、创建时间等 doc_info,且无法控制页面旋转方向。关键点在于:合并前手动提取并注入元数据,且逐页插入而非整份追加。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
- 用
fitz.open()打开每个PDF,遍历其page对象,再new_doc.insert_pdf(src_doc, from_page=i, to_page=i)插入——这样保留每页的旋转、缩放、裁剪信息 - 合并后统一设元数据:
new_doc.set_metadata({"title": "merged", "author": "auto"}) - 若需按文件名排序合并,别用
os.listdir()(无序),改用sorted(glob.glob("*.pdf"))或sorted(Path(".").glob("*.pdf"))
处理扫描PDF或含图片的文档时要注意什么?
这类PDF本质是“一页一图”,PyPDF2 和 fitz 都无法提取文字内容,但拆分/合并操作本身不受影响。真正的问题出在:文件体积暴增、OCR层错位、甚至部分阅读器显示为空白页。
- 拆分前先确认是否真需要操作——很多扫描PDF其实只需按页保存为独立文件,用
fitz的get_pixmap()提取图像反而更慢 - 合并后若发现页面空白,大概率是源PDF使用了非标准色彩空间(如
DeviceN),可用fitz.Page.get_text("dict")测试是否能获取文本框坐标来判断结构完整性 - 不要对扫描PDF尝试
PyPDF2的add_outline_item()—— 书签依赖文本结构,没文字就加不上
PDF 的“看似简单”背后是 ISO 32000 标准的复杂分层,自动化脚本里最常被忽略的不是语法,而是对 PDF 实际构成的理解:它可能是一堆向量指令、一张图、一段文字流,或三者混杂。选库之前,先用 fitz 打开看看 doc.page_count 和 doc[0].get_text() 返回啥,比硬套教程管用得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










