pypdf 快速上手:Python PDF 处理的合并、拆分与加密速查
【免费下载链接】pypdfA pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files项目地址: https://gitcode.com/GitHub_Trending/py/pypdf
pypdf 是一个纯 Python 实现的 PDF 处理库,解决读取、提取文本、合并拆分页面、加密解密、读写元数据这类日常文档问题。零 C 扩展依赖,pip 一行装好;核心入口只有 PdfReader 与 PdfWriter 两个对象,本文把常用操作逐一跑通,读完就能直接上手。
🧠 心智模型:PdfReader 只读,PdfWriter 只写
先把分工记牢,后面所有操作都是它的变体:
- PdfReader 负责解析:给定路径或文件对象,给出
pages、metadata、outline等只读视图,原文件不会被改动。 - PdfWriter 负责输出:调用
write()时才生成新文件,写什么取决于你提前塞进去什么。 - 两者不共享状态:所谓"修改 PDF",实际流程永远是 Reader 读出来,把需要的页面通过
add_page复制进 Writer,再由 Writer 落盘。 - 想原样克隆一份文件,用
PdfWriter(clone_from=reader)即可跳过手动逐页复制。
一句话:读永远不写,写都来自读。理解了这一点,pypdf 的 API 就不会有 surprises。
快速安装 pypdf 并验证环境
pypdf 支持 Python 3.9+,核心没有任何必选第三方依赖。需要 AES 加解密装crypto,需要图像操作装image,全都要就装full:
pip install pypdf # 基础功能:读写、合并、拆分 pip install pypdf[crypto] # 追加 AES 加解密支持(推荐) pip install pypdf[full] # 全部可选依赖 python -c "import pypdf; print(pypdf.__version__)" # 验证安装用 pypdf 完成常见 PDF 任务
提取 PDF 文本:plain 与 layout 两种模式
文本提取是使用频率最高的操作。默认 plain 模式按内容流顺序输出文字;layout 模式按版式还原成定宽文本,适合保留多列结构的文档。
from pypdf import PdfReader reader = PdfReader("report.pdf") for page in reader.pages: print(page.extract_text()) # 需要保留版式时改用: # print(page.extract_text(extraction_mode="layout"))注意两点:提取效果取决于生成该 PDF 的工具,扫描版(没有文本层)提不出文字,需要走 OCR 路线;单页内容流特别大时,提取会占不少内存,官方文档 docs/user/extract-text.md 里给了用len(page.get_contents().get_data())先做预估的做法。
用 pypdf 合并多个 PDF 文件
合并不需要先读再逐页加,append一行就能吃掉整个文件;传pages元组还可以只取其中几页,比如pages=(0, 3)表示第 0 到第 2 页。
from pypdf import PdfWriter writer = PdfWriter() for path in ["a.pdf", "b.pdf", "c.pdf"]: writer.append(path) # 整个文件追加到末尾 # 只追加 d.pdf 的前 3 页: # writer.append("d.pdf", pages=(0, 3)) writer.write("merged.pdf")处理超大文件时可能触发 Python 解释器的递归上限,报RecursionError的话按 docs/user/merging-pdfs.md 的提示调高sys.setrecursionlimit。
把大 PDF 拆分成多个小文件
拆分和合并共用同一套读写套路:Reader 读、Writer 写,区别只在按索引挑哪几页。
from pypdf import PdfReader, PdfWriter reader = PdfReader("big.pdf") for start in range(0, len(reader.pages), 10): # 每 10 页一个文件 writer = PdfWriter() for i in range(start, min(start + 10, len(reader.pages))): writer.add_page(reader.pages[i]) writer.write(f"part_{start // 10 + 1}.pdf")add_page复制的是页面,原文件不受影响;想把某页插到中间位置,用writer.insert_page(page, index)。
给 PDF 加密并设置访问权限
encrypt的第一个参数是用户密码(打开文件用),可选再给 owner 密码(解锁权限用)。不指定algorithm时默认走 RC4,属于老算法,建议显式选 AES-256。
from pypdf import PdfReader, PdfWriter reader = PdfReader("draft.pdf") writer = PdfWriter(clone_from=reader) # 整份克隆,免逐页复制 writer.encrypt("open-pwd", owner_password="admin-pwd", algorithm="AES-256") writer.write("secured.pdf") # 解密读取:把密码直接交给 Reader locked = PdfReader("secured.pdf", password="open-pwd")注意:permissions_flag参数用来限制打开后的操作,取pypdf.constants里的UserAccessPermissions组合,例如UserAccessPermissions.PRINT | UserAccessPermissions.MODIFY,默认是全部放行;AES 算法依赖pypdf[crypto]里的加密后端,没装会报缺依赖。
读取与写入 PDF 元数据
元数据分普通字段和 XMP 两套,可以同时存在。reader.metadata取普通字段,reader.xmp_metadata取 XMP,两者都可能为 None,用前先判空。
写入走writer.add_metadata(字典),键用小写字段名,例如:
- 读:
meta = reader.metadata,再逐个取meta.title、meta.author、meta.creator、meta.creation_date - 写:
writer.add_metadata({"title": "季度报告", "author": "张三"}),然后照常writer.write("out.pdf") - 迁移文件时先
writer.add_metadata(reader.metadata)保留原值,再追加一次调用覆盖个别字段
旋转、缩放页面并叠加水印
页面对象自带rotate;更细的控制用Transformation链式拼变换矩阵,再add_transformation应用;把一整页叠到当前页上用merge_page,水印就是这么做的。
from pypdf import PdfReader, PdfWriter, Transformation reader = PdfReader("doc.pdf") page = reader.pages[0] page = page.rotate(90) # 整页旋转,返回新页面对象 page.add_transformation(Transformation().scale(sx=0.7, sy=0.7)) # 叠加水印页(水印通常是单独生成的 PDF 页): # page.merge_page(watermark_page) writer = PdfWriter() writer.add_page(page) writer.write("transformed.pdf")注意:Transformation的rotate、scale、translate可以链式组合;上面只缩放了内容,页面框大小不变,如果需要同步缩小页面尺寸,还得改page.mediabox。
⚠️ 常见坑速查
- 密码文件:构造 Reader 时不传
password,一访问内容就抛FileNotDecryptedError(位于pypdf.errors,属于PdfReadError家族),不是读不出来,是根本没解锁。 - strict 模式:
PdfReader(path, strict=True)会把格式瑕疵直接变成异常,排查坏文件时开,生产批量处理保持默认宽松。 - 大文件内存:提取文本要解析整条内容流,极端情况内存放大几十倍;坚持逐页处理,处理完释放引用。
- 提取乱码:多半是源文件字体缺 ToUnicode 映射,属于文件本身的问题,换 OCR 兜底。
- 递归上限:合并超大文件报
RecursionError时,调高sys.setrecursionlimit。
pypdf 不擅长什么:边界与选型
pypdf 的定位是对 PDF 文件对象做结构化操作:合并、拆分、加密、元数据、页面变换这些做得扎实。它不做排版和渲染——从零生成复杂版式的新文档、把 PDF 转成图片、对扫描件做 OCR 识别,这些场景更适合 ReportLab 类生成库、pdf2image 或 OCR 管线,和 pypdf 组合使用而不是互相替换。文本提取方面官方文档自己也承认效果随源文件而波动,重要流程建议加一层结果校验。
更多用法看 docs/user/ 下的分主题文档,回归用例集中在 tests/,加密相关行为以 tests/test_encryption.py 为准。
【免费下载链接】pypdfA pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files项目地址: https://gitcode.com/GitHub_Trending/py/pypdf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考