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)
相关页面
- PDF Oxide vs PyMuPDF — 详细对比
- PDF Oxide vs pypdf — 详细对比
- vs 所有 Python PDF 库 — 完整生态对比
- 性能基准测试 — 方法论和结果