
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 处理库能够对 PDF 页面进行拆分splitting、合并merging、裁剪cropping与变换transforming同时支持为 PDF 添加自定义数据、查看选项与密码并能提取文本和元数据。本文将围绕 README.md 展开结合仓库源码与官方用户文档带你掌握从安装、基本读写到高级页面操作、加解密与测试参与的完整技能。pypdf 是什么能力全景根据 README.md 的官方定义pypdf 具备以下核心能力页面级操作拆分splitting、合并merging、裁剪cropping、变换transformingPDF 页面内容扩展为 PDF 添加自定义数据、查看选项viewing options和密码信息提取从 PDF 中检索文本text与元数据metadata。从 pypdf/init.py 的公开导出可以看到库对外暴露的核心 API 包括PdfReader读取、PdfWriter写入/合并、PageObject页面对象、Transformation页面变换、PaperSize纸张尺寸、PageRange页面范围、DocumentInformation文档信息、PasswordType密码类型、ImageType图像类型以及__version__版本号等覆盖了日常 PDF 处理的绝大部分场景。项目采用 BSD-3-Clause 许可要求 Python 版本 3.9官方分类器声明支持 Python 3.9 至 3.14参见 pyproject.toml并已内置类型标注py.typed对静态类型检查友好。环境要求与安装基础安装使用 pip 安装 pypdfpip install pypdf加密相关扩展安装如需使用 AES 加密或解密需要安装额外依赖pip install pypdf[crypto]在 pyproject.toml 中可以查到完整的可选依赖组可选依赖组包含的依赖用途cryptocryptography3.0AES 加密/解密推荐的后端cryptodomePyCryptodomeAES 加密/解密的备选后端fontsfonttools字体相关处理imagePillow8.0.0图像处理rtl_textarabic-reshaper,python-bidi从右到左RTL文本支持full上述全部一键安装全部可选能力devflit,pip-tools,pre-commit,pytest-cov等开发与测试docsmyst_parser,sphinx,sphinx_rtd_theme构建文档注意自 pypdf 3.1.0 起库相对旧版本有显著改进。若你从早期版本升级建议阅读仓库中的迁移指南 docs/meta/migration-1-to-2.md。快速上手读取 PDF 并提取文本README.md 给出了最核心的入门示例——打开 PDF、获取页数、读取第一页并提取文本from pypdf import PdfReader reader PdfReader(example.pdf) number_of_pages len(reader.pages) page reader.pages[0] text page.extract_text()PdfReader 的关键构造参数从 pypdf/_reader.py 的PdfReader.__init__源码可以看到除了stream文件对象、支持 read/seek 的对象或文件路径字符串之外还有三个重要参数strict是否对 PDF 的所有问题给出警告并让部分可纠正问题变为致命错误默认Falsepassword初始化时解密 PDF 的密码默认None不解密root_object_recovery_limit非严格模式下恢复 Root 对象时最多查询的对象数量安全防护措施传None可关闭。提示PdfReader初始化会读取 PDF 的交叉引用表cross-reference table到内存因此对于超大文件初始化阶段可能耗时。extract_text 的进阶用法extract_text并不只有读出全部文本这一种用法。根据 docs/user/extract-text.md它支持按方向过滤与排版模式控制from pypdf import PdfReader reader PdfReader(test Orient.pdf) page reader.pages[0] # 默认提取全部文本 print(page.extract_text()) # 只提取正向up文本 print(page.extract_text(0)) # 提取正向 左转 90° 的文本 print(page.extract_text((0, 90))) # 固定宽度layout模式尽量贴近源 PDF 的渲染排版 print(page.extract_text(extraction_modelayout)) # 保留水平位置、移除多余空行去掉纯空白行 print(page.extract_text(extraction_modelayout, layout_mode_space_verticallyFalse)) # 调整水平间距权重 print(page.extract_text(extraction_modelayout, layout_mode_scale_weight1.0)) # 默认排除旋转文本设为 False 则包含相对页面旋转的文本 print(page.extract_text(extraction_modelayout, layout_mode_strip_rotatedFalse))在复杂文档中正文内容流的解析可能占用大量内存官方文档给出过一个极端案例约 300 MB 未压缩内容流可能消耗 10 GB 内存。官方建议先检查len(page.get_contents().get_data())再决定是否处理以避免 OOM。另外如果页面只是扫描图像无文本层提取结果可能为空或极少此时应改用 OCR 软件如 Tesseract处理——pypdf 本身不是 OCR 软件也无法从纯图像中提取文本。使用 visitor 回调精确控制提取extract_text支持传入两个 visitor 回调函数实现按需处理页面局部内容visitor_text每个文本片段回调一次携带 5 个参数——text当前文本最长可为整行、user_matrix用户坐标系/CTM 矩阵、tm_matrix文本坐标系矩阵、font_dictionary完整字体字典未知字体时可能为None、font_size文本坐标系下的字号。矩阵的 6 个参数中前 4 个是旋转/缩放矩阵后 2 个是平移水平/垂直。官方推荐使用user_matrix因为它已包含全部变换若需从文本空间到用户空间的完整变换可用pypdf.mult(tm, cm)计算。visitor_operand_before每个操作符执行前回调携带 4 个参数——操作符、操作数参数、当前变换矩阵、文本矩阵。典型应用是忽略页眉页脚读取第 4 页并只保留50 y 720或y 0范围内的文本从而去掉页眉y 720和页脚y 50from pypdf import PdfReader reader PdfReader(GeoBase_NHNC1_Data_Model_UML_EN.pdf) page reader.pages[3] parts [] def visitor_body(text, cm, tm, font_dict, font_size): y tm[5] if 50 y 720 or y 0: parts.append(text) page.extract_text(visitor_textvisitor_body) text_body .join(parts)另一个官方示例是用visitor_operand_before捕获rerectangle操作符、用visitor_text捕获文本坐标把第 3 页导出为 SVG 图形便于可视化理解页面布局注意PDF 与 SVG 坐标系相反生成的 SVG 是自下而上的。为什么文本提取如此困难docs/user/extract-text.md 用整整一节解释了文本提取的难点理解这些对合理设置预期至关重要目标不明确段落换行放哪里页码、页眉页脚、轮廓outlines、表格、题注要不要提取粗体/斜体格式如何表示连字如 Unicode 的 UFB00 ff解析为单字符还是ff公式、脚注、超链接、浮动图与段落的位置关系如何处理缺少语义层PDF 格式是为打印出正确的视觉效果设计的不是为机器解析设计的文件中根本没有页眉、页脚、表格、段落这些语义信息只能靠启发式猜测。绝对定位与空白PDF 中每个字符都可以被绝对定位文本可能被表示为[(This is a )9(te)-3(st)9( do)-4(cu)13(m)-4(en)12(t )-3(b)3(y)-3( )9(Et)-2(h)3(an)4( Nels)13(o)-5(n)3(.)] TJ这种带数字微调的复杂形式导致空白字符很难精确还原。pypdf 与 OCR 的定位差异pypdf 是文本提取库而非 OCR 软件。它直接读取文件中的字符编码与字体信息因此永远不会混淆oO0ö这类相似字符也能处理 OCR 难以识别的罕见字符如 emoji。但面对扫描生成的 PDF纯图像pypdf 无能为力面对扫描仪 OCR 后的 PDF图像 后台文本层pypdf 可以提取后台文本层但错误可能层层累积官方建议此时直接使用 OCR 软件。文档还指出防止文本提取的手段图片化、乱码字体无法彻底阻止提取因为只要文档可读截图OCR 就是兜底方案。页面操作拆分、合并、裁剪与变换合并 PDFappend 与 mergeREADME.md 提到的拆分、合并能力在 docs/user/merging-pdfs.md 中有完整的实战示例。最基本的合并是把多个 PDF 依次追加from pypdf import PdfWriter merger PdfWriter() for pdf in [example.pdf, hello-world.pdf, jpeg.pdf]: merger.append(pdf) merger.write(out-basic.pdf)PdfWriter.append已相对早期版本做了扩展支持文件路径、文件对象和PdfReader三种输入并支持页面范围与书签参数from pypdf import PdfWriter, PdfReader writer PdfWriter() source_file_name GeoBase_NHNC1_Data_Model_UML_EN.pdf # 追加文件的前 10 页 writer.append(source_file_name, (0, 10)) reader PdfReader(source_file_name) # 从 reader 追加第 1 页和第 10 页并创建大纲outline writer.append(reader, page 1 and 10, [0, 9])合并过程中相关的命名目标named destination也会一并导入。若要在目标 PDF 中间插入页面应使用提供插入位置的mergewith ( open(Seige_of_Vicksburg_Sample_OCR.pdf, rb) as input1, open(two-different-pages.pdf, rb) as input2, open(example.pdf, rb) as input3, ): # 追加 input1 的前 3 页 merger.append(fileobjinput1, pages(0, 3)) # 在第 2 页之后插入 input2 的第 1 页 merger.merge(position2, fileobjinput2, pages(0, 1)) # 把整个 input3 追加到末尾 merger.append(input3) merger.write(out-advanced.pdf)同一页面还可以借助列表语法重复插入多次# 依次插入第 1、2、3、2、1 页0 为第 1 页 writer.append(reader, [0, 1, 0, 2, 0])官方文档建议优先使用append/mergeadd_page/insert_page并非首选路径。合并表单避免字段名冲突当合并的表单包含同名字段时部分数据可能无法访问。官方方案是在添加源 PDF 之前先添加一个分组字段reader.add_form_topname(form1)此后原名为field1的字段在reader.get_form_text_fields(True)或reader.get_fields()中会以form1.field1的形式出现从而避免命名冲突。之后再用writer.append/writer.merge整体或部分追加即可按页插入时只列出该页涉及的字段。页面旋转处理与高级克隆旋转页面合并若源页面带有旋转合并前建议调用page.transfer_rotation_to_content()把旋转烧入内容流避免合并后出现错误的旋转效果background PdfReader(jpeg.pdf).pages[0] for page in writer.pages: if page.rotation ! 0: page.transfer_rotation_to_content() page.merge_page(background, overFalse)对象克隆机制append/merge/add_page/insert_page在合并时会自动克隆相关对象避免页面/对象之间的副作用。手动挂接对象前可以用任意PdfObject的clone方法from pypdf.generic import StreamObject stream_object StreamObject() cloned_object stream_object.clone(writer) # 已属于 writer 的对象 clone 后返回自身 assert cloned_object stream_object.clone(writer) # 同一对象 clone 两次返回同一个克隆体 assert stream_object.clone(writer) stream_object.clone(writer)克隆是递归的克隆一个页面会连同其引用的所有对象包括IndirectObject指向的对象一起克隆。例如克隆带文章线索/B的页面会连带所有串联文章及其所在页面可能导致输出 PDF 体积膨胀。此时可用excluded_keys跳过指定字典键new_page writer.add_page(reader.pages[0], excluded_keys[/B])如需重置克隆映射例如同一 reader 再次追加时想得到新对象调用writer.reset_translation(reader)即可。裁剪与变换裁剪与变换的完整教程见 docs/user/cropping-and-transforming.md。在 pypdf 中页面几何由PageObject上的盒子属性如mediabox、cropbox、bleedbox、trimbox、artbox定义通过调整这些盒子即可实现裁剪而pypdf.Transformation在 pypdf/_page.py 中实现配合PageObject.add_transformation()可完成平移、缩放、旋转、倾斜等页面变换官方文档还提供了按页裁剪、拼接多页N-up等实战案例。元数据的读取与写入则参考 docs/user/metadata.md对应实现类DocumentInformation位于 pypdf/_doc_common.py。加密与解密PDF 加密基于 RC4 与 AES 算法不同密钥长度pypdf 支持直到 PDF-2.0 标准的所有方案。AES 相关的加密/解密需要额外依赖推荐使用pyca/cryptography即pip install pypdf[crypto]也可选用PyCryptodomepypdf[cryptodome]。加密 PDFfrom pypdf import PdfReader, PdfWriter reader PdfReader(example.pdf) writer PdfWriter(clone_fromreader) # 为 PDF 添加密码 writer.encrypt(my-secret-password, algorithmAES-256) writer.write(out-encrypt.pdf)algorithm参数的可选值为RC4-40、RC4-128、AES-128、AES-256-R5、AES-256官方推荐使用AES-256-R5。安全警告如果不传algorithm参数pypdf 出于兼容性考虑默认使用RC4。RC4 已被证实不安全生产环境务必显式指定 AES 系列算法。解密 PDFfrom pypdf import PdfReader, PdfWriter reader PdfReader(encrypted-file.pdf) if reader.is_encrypted: reader.decrypt(test) # 正确密码 writer PdfWriter(clone_fromreader) writer.write(out-decrypt.pdf)先通过reader.is_encrypted判断是否加密再调用reader.decrypt(password)传入密码PdfWriter(clone_fromreader)可以把解密后的内容克隆到新 writer 并写出。更完整的说明含算法细节与安装前提见 docs/user/encryption-decryption.md。从源码结构看实现在深入使用之前了解 pypdf/ 目录的模块划分有助于定位问题_reader.pyPdfReader负责解析交叉引用表、对象流与页面树_writer.pyPdfWriter负责写入、合并append/merge、克隆与加密_page.pyPageObject与Transformation页面级操作的核心_encryption.py加密/解密实现定义PasswordType与EncryptAlgorithm_crypt_providers/加密后端抽象支持_cryptography与_pycryptodome两种实现_text_extraction/文本提取引擎含_layout_mode/固定宽度布局模式与_text_extractor.pygeneric/PDF 底层对象模型字典、数组、流、间接引用等_codecs/PDF 字体编码与字形映射如adobe_glyphs.py、pdfdoc.pyconstants.py、errors.py、pagerange.py、papersizes.py、xmp.py常量、异常、页面范围、纸张尺寸与 XMP 元数据。例如pypdf/init.py 在导入时会探测crypt_provider与PIL版本并组装_debug_versions排查问题时可用print(pypdf.__version__)与print(pypdf._debug_versions)快速汇报环境。运行测试与参与贡献README 指出 pypdf 带有一套可用pytest执行的测试套件$ pytest仓库中的测试代码集中在 tests/ 目录覆盖读者/写入器、页面、合并、加密、过滤器、字体、表单、文本提取、XMP、分页范围与纸张尺寸等模块如test_reader.py、test_writer.py、test_merger.py、test_encryption.py、test_text_extraction.py。pyproject.toml 中已配置testpaths [tests]并启用了--disable-socket禁止测试联网与filterwarnings [error]警告即错误等严格策略另有slow、samples、enable_socket三类 pytest marker 用于区分测试规模。README 还给出了贡献规范QA用户可以在 StackOverflow 的pypdf标签、项目讨论区回答提问并为报告 issue 的用户索取最小完整可复现示例MCVE即代码 示例 PDF。Issues好的 bug 报告必须包含 MCVE——上传导致 bug 的 PDF、可执行的复现代码及全部输出并用print(pypdf.__version__)标明版本。Code欢迎各类代码贡献规模较小的 PR 更容易及时合入为新功能补充单元测试、为已修复 bug 补充回归用例有助于保证 PR 质量。详细流程见 CONTRIBUTING.md。结语pypdf 以纯 Python、零编译依赖的方式覆盖了 PDF 处理的主流需求从一行代码读取文本到按页范围合并、表单去冲突、页面旋转校正再到 RC4/AES 全系列加解密。结合 README.md、docs/user/ 下的官方教程与 pypdf/ 源码你可以按安装 → 读取提取 → 页面操作 → 加解密 → 测试验证的路径快速构建自己的 PDF 处理流水线。遇到文本提取结果不理想时请记住这是 PDF 格式缺乏语义层的固有限制而非库的缺陷明确输入文档类型数字原生 / 扫描 / OCR 层选择 pypdf 或 OCR 工具才能得到最可靠的结果。【免费下载链接】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),仅供参考