PDF Oxide vs PyMuPDF
PDF Oxide 是 PyMuPDF 的 MIT 协议替代方案:快 5.8 倍,还能免去 AGPL 带来的合规成本。无论你是在评估 PyMuPDF 用于商业项目,还是正想因许可证问题把它换掉,这页把关键差异都摆了出来。
为什么团队会从 PyMuPDF 迁走
许可证。 PyMuPDF 封装的是 AGPL-3.0 协议的 MuPDF。只要你分发包含 PyMuPDF 的软件(SaaS、Web 应用、Docker 镜像等),要么把全部代码按 AGPL 开源,要么向 Artifex 购买商业授权。PDF Oxide 使用 MIT 协议,完全没有这类约束。
速度。 PDF Oxide 平均 0.8 ms 完成文本抽取,PyMuPDF 需要 4.6 ms。在 3830 个 PDF 上差距是 5.8 倍。
稳定性。 同一份语料,PDF Oxide 通过率 100 %;PyMuPDF 是 99.3 %,在 27 个合法 PDF 上会失败。
快速对比
| PDF Oxide | PyMuPDF | |
|---|---|---|
| 许可证 | MIT | AGPL-3.0 |
| 平均抽取时间 | 0.8 ms | 4.6 ms |
| 通过率 (3830 PDF) | 100% | 99.3% |
| 文本抽取 | 支持 | 支持 |
| 字符位置 | 支持 | 支持 |
| 图片抽取 | 支持 | 支持 |
| 表单字段 | 读 + 写 | 读 + 写 |
| PDF 生成 | 支持 (Markdown/HTML) | 支持 |
| Markdown 输出 | 支持 | 不支持 |
| HTML 输出 | 支持 | 不支持 |
| 加密 | 读 + 写 | 读 + 写 |
| 渲染 | 支持 | 支持 |
| OCR | 内置 (PaddleOCR) | Tesseract |
| 安装体积 | 约 5 MB | 约 20 MB |
| Python 版本 | 3.8–3.14 | 3.8–3.12 |
代码并排对照
文本抽取
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)
PyMuPDF:
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
text = page.get_text()
print(text)
Markdown 转换
PDF Oxide (内置):
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
md = doc.to_markdown(0, detect_headings=True)
print(md)
PyMuPDF:
# PyMuPDF 没有内置的 Markdown 转换
# 需要改用 pymupdf4llm (独立包,比 PDF Oxide 慢 69 倍):
import pymupdf4llm
md = pymupdf4llm.to_markdown("paper.pdf")
图片抽取
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:
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"])
从 Markdown 生成 PDF
PDF Oxide:
from pdf_oxide import Pdf
pdf = Pdf.from_markdown("# Invoice\n\n| Item | Price |\n|------|-------|\n| Widget | $9.99 |")
pdf.save("invoice.pdf")
PyMuPDF:
import fitz
# PyMuPDF 无法从 Markdown 直接生成 PDF
# 必须手动在页面上摆放文本:
doc = fitz.open()
page = doc.new_page()
page.insert_text(fitz.Point(72, 72), "Invoice", fontsize=24)
doc.save("invoice.pdf")
基准测试细节
基准数据来自三套独立公开测试集 (veraPDF、Mozilla pdf.js、DARPA SafeDocs) 合计 3830 个 PDF。
| 指标 | PDF Oxide | PyMuPDF |
|---|---|---|
| 平均抽取时间 | 0.8 ms | 4.6 ms |
| p99 抽取时间 | 9 ms | 28 ms |
| 通过率 (合法 PDF) | 100% (3823/3823) | 99.3% (3796/3823) |
| 文本质量一致度 | 99.5% | 基线 |
语料构成与复现步骤见 完整基准方法。
AGPL 到底意味着什么
PyMuPDF 封装了 MuPDF,而 MuPDF 使用 AGPL-3.0。下列情形都会被这条协议覆盖:
- 对外分发使用 PyMuPDF 的软件(二进制、Docker 镜像、Electron 应用)
- 运营 SaaS,由 PyMuPDF 在自己的服务器上处理用户 PDF
- 把 PyMuPDF 嵌入产品 —— 哪怕放在 API 背后当作微服务
无论哪种情形,AGPL 都会要求你把整个应用的源代码按 AGPL-3.0 开源,或者向 Artifex 购买商业授权。
PDF Oxide 使用 MIT 协议。无论是商业、闭源、SaaS 还是开源项目,都可以直接用,没有额外义务。
| 使用场景 | PDF Oxide (MIT) | PyMuPDF (AGPL) |
|---|---|---|
| 商业产品 | 可用 | 需购买授权 |
| 闭源 SaaS | 可用 | 需购买授权 |
| 内部工具 | 可用 | 可用 |
| 开源项目 | 可用 | 可用 (若与 AGPL 兼容) |
| Docker 分发 | 可用 | 需购买授权 |
PyMuPDF 商业授权价格
Artifex (MuPDF 与 PyMuPDF 背后的公司) 并未公开商业授权价格。根据业界反馈:
- 必须联系销售 —— 只能向 Artifex 销售团队索取报价
- 按应用授权 —— 价格随部署形态与规模变动
- 按年付费 —— 商业授权通常按年续约
- 没有免费档 —— AGPL 下并不存在「社区版」或「创业版」之类的豁免
对于评估商用 PyMuPDF 的团队,许可证是一笔除开发成本外长期存在的运营支出。
PDF Oxide 使用 MIT 协议 —— 任何用途永久免费。 没有销售来电、没有授权审计、没有合规风险。SaaS、Docker 分发、嵌入商业产品都可以直接用,毫无限制。
迁移指南
API 对照
| 任务 | PyMuPDF | PDF Oxide |
|---|---|---|
| 打开 PDF | fitz.open("f.pdf") |
PdfDocument("f.pdf") |
| 页数 | doc.page_count |
doc.page_count() |
| 抽取文本 | doc[0].get_text() |
doc.extract_text(0) |
| 字符数据 | doc[0].get_text("dict") |
doc.extract_chars(0) |
| 抽取图片 | doc[0].get_images() + doc.extract_image(xref) |
doc.extract_images(0) |
| 文本搜索 | doc[0].search_for("query") |
doc.search_page(0, "query") |
| 加密 PDF | doc.authenticate("pw") |
PdfDocument("f.pdf", password="pw") |
| 输出 Markdown | pymupdf4llm (独立包) | doc.to_markdown(0) |
| 从文本生成 | 手动 insert_text() |
Pdf.from_markdown("# 标题") |
步骤
- 安装:
pip install pdf_oxide - 替换导入:
import fitz→from pdf_oxide import PdfDocument - 替换打开方式:
fitz.open(path)→PdfDocument(path) - 替换抽取方式:
page.get_text()→doc.extract_text(page_index) - 替换图片流程: 多步 xref 查找 →
doc.extract_images(page_index) - 调整密码处理: 使用
PdfDocument(path, password="pw"),或打开后调用doc.authenticate("pw") - 回归测试: 把原有测试文件跑一遍流水线
什么情况下仍选择 PyMuPDF
- 已有 MuPDF 商业授权,并依赖 MuPDF 独有的渲染效果
- 需要导出 SVG(PDF Oxide 不输出 SVG)
- 项目本身就采用 AGPL 协议
相关页面
- 性能基准 —— 完整语料结果
- vs Python PDF 库 —— 所有 Python 库横向对比
- Python 入门 —— 安装与首次抽取