pypdf2 3.0+ 版本移除 getpage(),改用 reader.pages[0] 访问页;合并时书签丢失需用 pikepdf 或 fitz;旋转应限 90° 倍数并校正 mediabox;复杂操作推荐 fitz。

用 PyPDF2 拆分 PDF 时为什么 getPage() 报错?
PyPDF2 从 3.0 版本起彻底移除了 getPage() 方法,改用基于零索引的 pages 属性访问页对象。旧代码如 pdf_reader.getPage(0) 会触发 AttributeError。
- 正确写法是:
pdf_reader.pages[0](返回PageObject) - 拆分单页示例:
from PyPDF2 import PdfReader, PdfWriter<br>reader = PdfReader("input.pdf")<br>writer = PdfWriter()<br>writer.add_page(reader.pages[2]) # 提取第3页<br>with open("page3.pdf", "wb") as f:<br> writer.write(f) - 批量拆分注意:页码越界会抛
IndexError,建议用len(reader.pages)校验范围
合并多个 PDF 时中文目录/书签丢失怎么办?
PyPDF2 默认不保留源文件的 outline(即书签结构),且对含中文元数据的 PDF 兼容性差。若需保留书签,必须显式调用 add_outline_item() 或改用 pikepdf。
- 基础合并(无书签):
writer.append(reader)比循环add_page()更高效 - 保留书签的替代方案:
import pikepdf<br>pdf = pikepdf.Pdf.new()<br>for fname in ["a.pdf", "b.pdf"]:<br> src = pikepdf.Pdf.open(fname)<br> pdf.add_pages(src.pages)
- PyPDF2 中手动重建书签极繁琐,且无法还原层级关系,不推荐用于生产环境
旋转 PDF 页面后内容错位或空白?
PDF 页面旋转本质是修改 /Rotate 字典项,但部分阅读器(尤其移动端)对非 90° 倍数的旋转支持不佳;更关键的是,PyPDF2 的 rotate() 方法默认旋转 *页面内容* 而非 *显示方向*,易导致裁剪异常。
- 安全做法:只使用
90、180、270三个参数值 - 旋转后务必调用
page.mediabox校正尺寸(例如page.rotate(90)后,宽高互换) - 常见陷阱:
page.rotate(90)不等价于“顺时针转一页”,它仅更新旋转标记,实际渲染依赖阅读器解析逻辑
为什么 fitz(PyMuPDF)比 PyPDF2 更适合复杂操作?
PyPDF2 纯 Python 实现,处理加密、注释、字体嵌入等场景能力弱;而 fitz 是 MuPDF 的 Python 绑定,底层 C 实现,支持直接编辑内容流、提取图像、OCR 集成等。
- 旋转+重置尺寸一步到位:
import fitz<br>doc = fitz.open("input.pdf")<br>page = doc[0]<br>page.set_rotation(90) # 自动适配 mediabox - 合并时可保留所有元数据:
doc.insert_pdf(other_doc, start_page=0) - 注意:PyMuPDF 默认不包含在标准库,需
pip install PyMuPDF,且商用需留意其 AGPL 许可限制
实际处理 PDF 时,页级操作(如拆分、简单旋转)用 PyPDF2 足够;一旦涉及书签、加密、注释或需要像素级控制,fitz 几乎是唯一可靠选择。别在 PyPDF2 里硬扛书签重建——那不是 bug,是设计边界。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











