Skip to content

PyMuPDF vs pypdf — 该选哪个 Python PDF 库?

PyMuPDF 和 pypdf 是最流行的两个 Python PDF 库,但它们各有明显的短板。PyMuPDF 速度快,但受限于 AGPL-3.0 许可证。pypdf 采用宽松许可,但速度慢了 15 倍。本文将两者直接对比,并说明为什么 PDF Oxide 是比它们更好的选择

简短结论: PDF Oxide 比 PyMuPDF 快 5.8 倍,比 pypdf 快 15 倍,采用 MIT 许可,功能也比两者更全面——包括内置 Markdown/HTML 输出、XFA 表单支持以及无需系统依赖的 OCR。

快速对比

PyMuPDF pypdf PDF Oxide
许可证 AGPL-3.0 BSD-3 MIT
底层语言 C (MuPDF) Pure Python Rust + PyO3
平均提取耗时 4.6ms 12.1ms 0.8ms
p99 提取耗时 28ms 97ms 9ms
通过率 (3,830 个 PDF) 99.3% 98.4% 100%
文本提取 支持 支持 支持
字符位置 支持 部分支持 支持
图片提取 支持 支持 支持
表单字段 读写 读写 读写
PDF 创建 支持 有限(仅合并) 支持(Markdown/HTML)
Markdown 输出 不支持 不支持 支持
HTML 输出 不支持 不支持 支持
渲染 支持 不支持 支持
OCR Tesseract 不支持 内置(PaddleOCR)
安装体积 ~20 MB ~1 MB ~5 MB
加密 读写 读写 读写
搜索 支持 不支持 正则 + 空间搜索
Python 版本 3.8–3.12 3.6+ 3.8–3.14

PyMuPDF 比 pypdf 更快、功能更丰富,但 AGPL 许可证让很多商业项目望而却步。pypdf 更轻量且采用 BSD 许可,但速度慢得多,提取能力也更有限。PDF Oxide 兼具原生引擎的速度优势和宽松许可的自由度。

许可证对比:AGPL vs BSD vs MIT

PyMuPDF 和 pypdf 之间的许可证差异,往往是团队做技术选型时的决定性因素。

PyMuPDF — AGPL-3.0

PyMuPDF 封装的是 MuPDF,后者采用 AGPL-3.0 许可。这是一种强 copyleft 许可证。如果你分发任何使用了 PyMuPDF 的软件——包括 SaaS 应用、Docker 容器、Web 服务、桌面应用或 CLI 工具——你的整个应用都必须以 AGPL-3.0 发布,也就是说必须公开全部源代码。

替代方案是向 MuPDF 背后的公司 Artifex 购买商业许可。Artifex 不公开定价,需要联系销售团队获取报价。商业许可通常按年收费,按应用计价。

AGPL 会影响你的情况:

  • 发布包含 PyMuPDF 的产品(桌面应用、移动应用、Electron)
  • 运行使用 PyMuPDF 处理 PDF 的 SaaS 或 Web 服务
  • 分发包含 PyMuPDF 的 Docker 镜像
  • 提供内部使用 PyMuPDF 的 API 服务

AGPL 不影响你的情况:

  • 项目已经以 AGPL 兼容许可证开源
  • 仅在内部工具中使用 PyMuPDF,从不对外分发

pypdf — BSD-3

pypdf 采用 BSD 3-Clause 许可证,属于宽松许可。你可以在商业产品、闭源软件和 SaaS 应用中使用 pypdf,无需公开源代码。唯一的要求是在再分发时保留版权声明。

PDF Oxide — MIT

PDF Oxide 采用 MIT 许可——最宽松的常见开源许可证。可在任何场景下使用(商业、闭源、SaaS、开源),除了保留许可证文本外没有其他限制。

许可证总结

使用场景 PyMuPDF (AGPL) pypdf (BSD) PDF Oxide (MIT)
商业产品 需购买许可 可以 可以
闭源 SaaS 需购买许可 可以 可以
Docker 分发 需购买许可 可以 可以
内部工具 可以 可以 可以
开源(AGPL 兼容) 可以 可以 可以
开源(MIT/BSD/Apache) 不可以 可以 可以

对于注重许可证合规的商业项目,pypdf 和 PDF Oxide 都是安全的选择。PyMuPDF 则要求你要么开源整个应用,要么购买商业许可。

速度基准测试

所有基准测试都在同一个 3,830 个 PDF 的语料库上运行——包含三个独立的公开测试集(veraPDF、Mozilla pdf.js、DARPA SafeDocs),覆盖所有 PDF 规范版本(1.0–2.0)、加密文件、CJK 编码、复杂布局和格式错误的文档。

文本提取速度

平均 p99 相对 PDF Oxide
PDF Oxide 0.8ms 9ms 1x
PyMuPDF 4.6ms 28ms 慢 5.8 倍
pypdf 12.1ms 97ms 慢 15.1 倍

PyMuPDF 比 pypdf 快 2.6 倍,因为它将解析工作委托给了 MuPDF 的 C 引擎。pypdf 所有工作都在纯 Python 中完成——解析、字体解码、文本组装——每个操作都要承受解释器的开销。

PDF Oxide 比两者都快,因为其 Rust 内核通过 PyO3 原生处理所有 PDF 解析、字体解码和文本排版,只有最终结果才跨越 Python 边界。没有子进程开销,没有通过 ctypes 桥接 C 库,也没有解释器瓶颈。

可靠性

通过的有效 PDF 通过率
PDF Oxide 3,823 / 3,823 100%
PyMuPDF 3,796 / 3,823 99.3%
pypdf 3,762 / 3,823 98.4%

PyMuPDF 在语料库中的 27 个有效 PDF 上失败。pypdf 在 61 个上失败。这些都是完全有效的 PDF 文件,库要么崩溃,要么返回空白/错误的文本。PDF Oxide 处理所有 3,823 个有效 PDF 均无故障。

完整 3,830 个文件语料库中有 7 个未通过的文件是故意损坏的测试用例(缺少 PDF 头、模糊测试破坏的目录、无效的 xref 流),所有库的通过率计算都排除了这些文件。

实际意义

对于每天处理数千个 PDF 的流水线来说,PyMuPDF 99.3% 的通过率意味着每 1,000 个文档约有 7 个失败。pypdf 的 98.4% 意味着每 1,000 个有 16 个失败。这些文档你需要用兜底逻辑处理、人工审核,或者直接接受数据丢失。

PDF Oxide 在测试语料库上 100% 的通过率意味着生产环境中需要处理的边界情况更少。

功能对比

文本提取

三个库都支持基本的文本提取,API 风格各有不同:

PyMuPDF:

import fitz

doc = fitz.open("report.pdf")
page = doc[0]
text = page.get_text()
print(text)

pypdf:

from pypdf import PdfReader

reader = PdfReader("report.pdf")
text = reader.pages[0].extract_text()
print(text)

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)

PyMuPDF 使用页面对象模型(doc[0] 返回一个页面)。pypdf 使用 reader/pages 模式。PDF Oxide 直接使用页面索引。

对于字符级提取(位置、字体大小、边界框),PyMuPDF 提供 get_text("dict") 返回嵌套字典结构。pypdf 只提供部分字符位置数据。PDF Oxide 提供 extract_chars(),包含每个字符的边界框和字体元数据。

Markdown 转换

这是一个重要的差异化功能。许多 LLM 和 RAG 流水线都需要从 PDF 输出 Markdown。

PyMuPDF:

# PyMuPDF 没有内置 Markdown 转换。
# 需要安装 pymupdf4llm,一个独立的包:
import pymupdf4llm

md = pymupdf4llm.to_markdown("paper.pdf")

pymupdf4llm 能用,但比 PDF Oxide 内置的 Markdown 转换慢 69 倍(平均 55.5ms vs 0.8ms)。而且它是一个独立的依赖,有自己的维护周期。

pypdf:

# pypdf 没有 Markdown 转换功能。
# 你需要外部工具链(例如先提取文本,
# 再用另一个库将其格式化为 Markdown)。

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
md = doc.to_markdown(0, detect_headings=True)
print(md)

PDF Oxide 的 Markdown 转换是内置功能,支持标题检测、保留表格结构,速度与纯文本提取相同。

HTML 转换

PyMuPDF: 不支持内置 HTML 输出。

pypdf: 不支持 HTML 输出。

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")
html = doc.to_html(0)
print(html)

表单字段

三个库都支持读写表单字段(AcroForm)。

PyMuPDF:

import fitz

doc = fitz.open("form.pdf")
page = doc[0]
for widget in page.widgets():
    print(f"{widget.field_name}: {widget.field_value}")

pypdf:

from pypdf import PdfReader

reader = PdfReader("form.pdf")
fields = reader.get_fields()
for name, field in fields.items():
    print(f"{name}: {field.get('/V', '')}")

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("form.pdf")
fields = doc.get_form_fields()
for field in fields:
    print(f"{field.name}: {field.value}")

一个值得注意的差异:PDF Oxide 支持 XFA 表单(XML Forms Architecture),这种格式在很多政府和企业 PDF 表单中广泛使用。PyMuPDF 和 pypdf 都不支持 XFA 表单数据提取。

图片提取

PyMuPDF:

import fitz

doc = fitz.open("report.pdf")
page = doc[0]
for i, img in enumerate(page.get_images()):
    xref = img[0]
    base_image = doc.extract_image(xref)
    with open(f"image_{i}.{base_image['ext']}", "wb") as f:
        f.write(base_image["image"])

pypdf:

from pypdf import PdfReader

reader = PdfReader("report.pdf")
page = reader.pages[0]
for i, image in enumerate(page.images):
    with open(f"image_{i}.{image.name.split('.')[-1]}", "wb") as f:
        f.write(image.data)

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
images = doc.extract_image_bytes(0)
for i, img in enumerate(images):
    with open(f"image_{i}.{img['format']}", "wb") as f:
        f.write(img["data"])

三个库都支持嵌入式图片提取。PyMuPDF 的方式需要两步 xref 查找。pypdf 和 PDF Oxide 提供了更简洁的 API。

渲染

PyMuPDF 可以使用 MuPDF 的渲染引擎将 PDF 页面渲染为图片(PNG、JPEG)。pypdf 完全不支持页面渲染。PDF Oxide 内置渲染引擎。

OCR

PyMuPDF 集成 Tesseract 对扫描 PDF 进行 OCR。pypdf 不支持 OCR。PDF Oxide 内置基于 PaddleOCR 的 OCR,无需任何外部系统依赖。

PDF 创建

PyMuPDF 可以创建 PDF,但需要手动在页面上放置文本、图片和形状——没有从结构化内容创建 PDF 的高级 API。

pypdf 无法从零创建 PDF。它可以合并、拆分和修改现有 PDF,但创建新 PDF 需要 reportlab 或 fpdf2 等独立库。

PDF Oxide 可以从 Markdown 或 HTML 创建 PDF:

from pdf_oxide import Pdf

pdf = Pdf.from_markdown("# Invoice\n\n| Item | Price |\n|------|-------|\n| Widget | $9.99 |")
pdf.save("invoice.pdf")

加密

三个库都支持读取加密 PDF 和写入加密输出。

PyMuPDF:

import fitz

doc = fitz.open("encrypted.pdf")
doc.authenticate("password")
text = doc[0].get_text()

pypdf:

from pypdf import PdfReader

reader = PdfReader("encrypted.pdf")
reader.decrypt("password")
text = reader.pages[0].extract_text()

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)

功能总结

功能 PyMuPDF pypdf PDF Oxide
文本提取 支持 支持 支持
字符位置 支持 部分支持 支持
图片提取 支持 支持 支持
表单字段 (AcroForm) 读写 读写 读写
XFA 表单 不支持 不支持 支持
PDF 创建 手动 不支持 Markdown/HTML
Markdown 输出 不支持 (pymupdf4llm) 不支持 内置
HTML 输出 不支持 不支持 内置
渲染 支持 不支持 支持
OCR Tesseract 不支持 内置 (PaddleOCR)
搜索 支持 不支持 正则 + 空间搜索
加密 读写 读写 读写
PDF/A 验证 不支持 不支持 支持
SVG 导出 支持 不支持 不支持
合并/拆分 支持 支持 支持

何时选择各库

选择 pypdf 的场景:

  • 需要纯 Python 方案,不想引入 C 或 Rust 编译扩展
  • 只做简单的 PDF 操作(合并、拆分、旋转、加密/解密)
  • 速度对你的场景不关键
  • 希望安装体积尽可能小(~1 MB)
  • 需要广泛的 Python 版本支持(3.6+)

选择 PyMuPDF 的场景:

  • 已经有 Artifex 的 MuPDF 商业许可
  • 需要将 PDF 页面导出为 SVG
  • 项目本身已经采用 AGPL-3.0 许可
  • 依赖 MuPDF 特定的渲染行为

选择 PDF Oxide 的场景:

  • 需要最快的文本提取速度(比 PyMuPDF 快 5.8 倍,比 pypdf 快 15 倍)
  • 需要 MIT 许可用于商业或闭源项目
  • 需要内置 Markdown 或 HTML 输出来对接 LLM/RAG 流水线
  • 需要 XFA 表单支持
  • 需要内置 OCR 且无需安装外部系统依赖
  • 需要对有效 PDF 100% 的可靠性

安装

# PyMuPDF
pip install pymupdf

# pypdf
pip install pypdf

# PDF Oxide
pip install pdf_oxide

三个库都可通过 pip 安装。PyMuPDF 附带 ~20 MB 的 wheel 包(内含 MuPDF)。pypdf 是纯 Python 实现,约 ~1 MB。PDF Oxide 提供预编译 wheel 包(~5 MB),支持 Linux (x86_64, aarch64)、macOS (x86_64, arm64) 和 Windows (x86_64)。

结论

如果你在 PyMuPDF 和 pypdf 之间纠结,那你其实是在速度和许可证自由度之间做选择。PDF Oxide 两者兼得——比 PyMuPDF 更快,比 pypdf 更宽松,还有两者都没有的功能。

你的需求 最佳选择
极致速度 PDF Oxide (0.8ms)
宽松许可 PDF Oxide (MIT) 或 pypdf (BSD)
速度 + 宽松许可 PDF Oxide — 唯一的选择
Markdown/HTML 输出 PDF Oxide — 内置
XFA 表单 PDF Oxide — 唯一支持的库
100% 可靠性 PDF Oxide — 100% 通过率
无需 Tesseract 的 OCR PDF Oxide — 内置 PaddleOCR
SVG 导出 PyMuPDF
纯 Python,无二进制文件 pypdf

10 秒上手:

pip install pdf_oxide
from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
text = doc.extract_text(0)

相关页面