Skip to content

2026 最佳 Python PDF 库对比

将 PDF Oxide 与 PyMuPDF (fitz)、pypdfium2、pypdf、pdfplumber、pdfminer 等库进行对比。本页从性能、功能覆盖、许可证和 API 差异几个维度,帮你挑选合适的 Python PDF 文本提取库。

概览

PDF Oxide PyMuPDF pypdfium2 pypdf pdfplumber pdfminer
平均提取时间 0.8ms 4.6ms 4.1ms 12.1ms 23.2ms 16.8ms
通过率(3830 个 PDF) 100% 99.3% 99.2% 98.4% 98.8% 98.8%
许可证 MIT AGPL-3.0 Apache-2.0 BSD-3 MIT MIT
实现语言 Rust + PyO3 C (MuPDF) C (PDFium) 纯 Python 纯 Python 纯 Python
文本提取 支持 支持 支持 支持 支持 支持
字符位置 支持 支持 支持 部分 支持 支持
图像提取 支持 支持 支持 支持 不支持 不支持
表单字段 读 + 写 读 + 写 只读 读 + 写 只读 不支持
PDF 创建 支持 支持 不支持 有限 不支持 不支持
PDF 编辑 支持 支持 不支持 支持 不支持 不支持
Markdown 输出 支持 不支持 不支持 不支持 不支持 不支持
HTML 输出 支持 不支持 不支持 不支持 不支持 不支持
加密 读 + 写 读 + 写 只读 读 + 写 不支持 不支持
PDF/A 校验 支持 不支持 不支持 不支持 不支持 不支持
渲染 支持 支持 支持 不支持 不支持 不支持
搜索 正则 + 空间检索 支持 支持 不支持 不支持 不支持
Python 版本 3.8–3.14 3.8–3.12 3.8+ 3.6+ 3.8+ 3.6+
安装大小 ~5 MB wheel ~20 MB wheel ~3 MB wheel ~1 MB ~1 MB ~1 MB

性能对比

每个 PDF 的平均文本提取时间,基于 3830 个 PDF 的完整语料。语料由三套公开可得的独立测试集组成,覆盖了 PDF 规范的所有版本(1.0–2.0)、加密文件、损坏文档、CJK 编码、复杂版式以及安全边缘场景。关于各测试集的内容以及结果可复现性,参见语料详情

平均 相对 p99 通过率
PDF Oxide 0.8ms 9ms 100%
PyMuPDF 4.6ms 5.8× 28ms 99.3%
pypdfium2 4.1ms 5.1× 42ms 99.2%
pymupdf4llm 55.5ms 69× 280ms 99.1%
pdftext 7.3ms 9.1× 82ms 99.0%
pdfminer 16.8ms 21× 124ms 98.8%
pdfplumber 23.2ms 29× 189ms 98.8%
markitdown 108.8ms 136× 378ms 98.6%
pypdf 12.1ms 15.1× 97ms 98.4%

PDF Oxide 的性能来自通过 PyO3 编译为 Python 扩展模块的原生 Rust 内核。没有子进程开销,也没有 C 库桥接——Rust 代码直接在 Python 进程内运行。

稳定性

PDF Oxide 在 3823 个有效 PDF 上全部处理成功,通过率 100%。3830 个语料中未通过的 7 个文件,是有意损坏的测试用例(缺失 PDF 头、被模糊测试破坏的目录、无效 xref 流)。

有效 PDF 通过数 通过率
PDF Oxide 3823 / 3823 100%
PyMuPDF 3796 / 3823 99.3%
pypdfium2 3792 / 3823 99.2%
pymupdf4llm 3787 / 3823 99.1%
pdftext 3784 / 3823 99.0%
pdfminer 3777 / 3823 98.8%
pdfplumber 3777 / 3823 98.8%
markitdown 3771 / 3823 98.6%
pypdf 3762 / 3823 98.4%

文本质量

在整个语料上,PDF Oxide 与 PyMuPDF、pypdfium2 的文本一致率为 99.5%。质量通过逐字符比对提取结果测量得出。剩余 0.5% 的差异集中在空白字符归一化和连字处理上,PDF Oxide 的输出更干净。

许可证对比

许可证 商业使用 Copyleft
PDF Oxide MIT 无限制
pypdfium2 Apache-2.0 无限制
PyMuPDF AGPL-3.0 需购买商业许可($)
pypdf BSD-3 无限制
pdfplumber MIT 无限制
pdfminer MIT 无限制
pdftext GPL-3.0 必须开源

PyMuPDF 基于 AGPL-3.0 授权的 MuPDF。一旦分发使用 PyMuPDF 的软件,你的软件同样要以 AGPL-3.0 开源,或向 Artifex 购买商业授权。SaaS 产品、Web 应用以及任何分发的二进制都受此约束。

PDF Oxide 采用 MIT 许可证,没有任何限制。可直接用于商业产品、SaaS 平台或闭源应用,无需承担授权义务。

场景 PDF Oxide (MIT) PyMuPDF (AGPL) pypdfium2 (Apache) pypdf (BSD) pdfplumber (MIT) pdfminer (MIT)
商业产品 可以 需授权 可以 可以 可以 可以
闭源 可以 否(无授权时) 可以 可以 可以 可以
SaaS / 云端 可以 需授权 可以 可以 可以 可以
内部工具 可以 可以 可以 可以 可以 可以

API 对比

文本提取

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)

pypdf:

from pypdf import PdfReader

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

pdfplumber:

import pdfplumber

with pdfplumber.open("report.pdf") as pdf:
    page = pdf.pages[0]
    text = page.extract_text()
    print(text)

pdfminer:

from pdfminer.high_level import extract_text

text = extract_text("report.pdf", page_numbers=[0])
print(text)

字符级提取

PDF Oxide:

from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
chars = doc.extract_chars(0)
for ch in chars:
    print(f"'{ch.char}' at ({ch.bbox[0]:.1f}, {ch.bbox[1]:.1f}) "
          f"size={ch.font_size:.1f}")

PyMuPDF:

import fitz

doc = fitz.open("report.pdf")
page = doc[0]
blocks = page.get_text("dict")["blocks"]
for block in blocks:
    if "lines" in block:
        for line in block["lines"]:
            for span in line["spans"]:
                print(f"'{span['text']}' size={span['size']:.1f}")

pdfplumber:

import pdfplumber

with pdfplumber.open("report.pdf") as pdf:
    page = pdf.pages[0]
    for char in page.chars:
        print(f"'{char['text']}' at ({char['x0']:.1f}, {char['top']:.1f}) "
              f"size={char['size']:.1f}")

pdfminer:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTChar

for page_layout in extract_pages("report.pdf"):
    for element in page_layout:
        if hasattr(element, '__iter__'):
            for text_line in element:
                if hasattr(text_line, '__iter__'):
                    for char in text_line:
                        if isinstance(char, LTChar):
                            print(f"'{char.get_text()}' at ({char.x0:.1f}, {char.y0:.1f}) "
                                  f"size={char.size:.1f}")

图像提取

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"])

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 创建

PDF Oxide:

from pdf_oxide import Pdf

pdf = Pdf.from_markdown("# Hello World\n\nThis is a PDF.")
pdf.save("output.pdf")

# 同样支持 HTML
pdf = Pdf.from_html("<h1>Hello</h1><p>World</p>")
pdf.save("output.pdf")

PyMuPDF:

import fitz

doc = fitz.open()
page = doc.new_page()
text_point = fitz.Point(72, 72)
page.insert_text(text_point, "Hello World", fontsize=24)
doc.save("output.pdf")

pypdf:

# pypdf 可以合并或修改 PDF,但无法从零创建带文本的 PDF。
# 先用 reportlab 或 fpdf2 生成,再用 pypdf 合并。

加密 PDF

PDF Oxide:

from pdf_oxide import PdfDocument

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

PyMuPDF:

import fitz

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

pypdf:

from pypdf import PdfReader

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

Markdown 与 HTML 输出

PDF Oxide(独家功能):

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")

# 转换为 Markdown,并识别标题
md = doc.to_markdown(0, detect_headings=True)
print(md)

# 转换为 HTML
html = doc.to_html(0)
print(html)

其他 Python PDF 库都不带内置的 Markdown 或 HTML 转换功能。

各库简介

PDF Oxide

优点:

  • Rust 内核带来基准测试中最快的文本提取速度——比 PyMuPDF 快 5.8×
  • 在 3830 个 PDF 语料上达到 100% 通过率,是所测库中稳定性最高的
  • 单个库提供统一的提取、创建、编辑 API
  • 内置带标题识别的 Markdown 与 HTML 导出
  • MIT 许可证,没有 copyleft(传染性开源)限制
  • 原生合规校验(PDF/A、PDF/UA、PDF/X)
  • 为主要平台与 Python 3.8–3.14 提供预编译 wheel
  • 无系统依赖——wheel 已包含一切所需

不足:

  • 上线时间较短,社区规模较小
  • 表格提取不如 pdfplumber 的算法细致
  • 渲染引擎的成熟度不及 MuPDF

PyMuPDF (fitz)

优点:

  • 成熟且经过生产检验(基于 MuPDF,自 2005 年起持续开发)
  • 对复杂 PDF 的渲染质量出色
  • 内置 OCR 集成(Tesseract)
  • 功能丰富:SVG 导出、页面操作、表格检测

不足:

  • AGPL-3.0 要求开源你的应用或购买商业许可
  • 因打包 MuPDF,wheel 体积较大(约 20 MB)
  • 没有内置的 Markdown 导出
  • 没有合规校验

pypdfium2

优点:

  • 速度快(基于 Google 的 PDFium 引擎)
  • Apache-2.0 许可证,商用宽松
  • 渲染质量良好

不足:

  • 文本提取 API 相比 PDF Oxide 或 PyMuPDF 更为有限
  • 无法创建或编辑 PDF
  • 表单字段仅支持只读

pypdf

优点:

  • 纯 Python,哪里都能装,没有编译依赖
  • 轻量,维护良好
  • 适合 PDF 操作(合并、拆分、旋转、加密)
  • 社区规模大,文档充足

不足:

  • 文本提取速度比 PDF Oxide 慢 15×
  • 遇到复杂版式时提取质量会下降
  • 无渲染、无 Markdown/HTML 输出、无表格提取

pdfplumber

优点:

  • Python PDF 库中最出色的表格提取
  • 字符级位置信息十分精细
  • 提供可视化调试工具(带标注的页面图像)
  • MIT 许可证

不足:

  • 纯 Python,比 PDF Oxide 慢 29×
  • 只读——无法创建或编辑 PDF
  • 不支持加密与渲染

pdfminer

优点:

  • 对字符与版式的分析细致
  • 对 CJK 文本支持良好
  • 是 pdfplumber 等工具的底座
  • MIT 许可证

不足:

  • 比 PDF Oxide 慢 21×(纯 Python,未优化)
  • 只读,没有创建或编辑
  • 常见任务的 API 偏繁琐
  • 维护不够活跃

如何选择

场景 推荐库
快速文本提取 PDF Oxide
商业 / 专有产品 PDF Oxide、pypdfium2、pypdf、pdfplumber 或 pdfminer
PyMuPDF 的 MIT 替代 PDF Oxide
从 Markdown/HTML 生成 PDF PDF Oxide
合规校验(PDF/A、PDF/X) PDF Oxide
发票等文档的表格提取 pdfplumber
提取过程的可视化调试 pdfplumber
已有 MuPDF 投入 PyMuPDF(AGPL 可接受时)
依赖尽量少 pypdf(纯 Python)
细致版式分析 pdfminer
扫描件 OCR PyMuPDF

安装

# PDF Oxide
pip install pdf_oxide

# PyMuPDF
pip install pymupdf

# pypdfium2
pip install pypdfium2

# pypdf
pip install pypdf

# pdfplumber
pip install pdfplumber

# pdfminer
pip install pdfminer.six

PDF Oxide 为 Linux(x86_64、aarch64)、macOS(x86_64、arm64)和 Windows(x86_64)提供预编译 wheel,无需编译器或系统库。

相关页面