Skip to content

pdfplumber vs PyMuPDF —— 速度、表格与许可证

pdfplumber 和 PyMuPDF 都是流行的 Python PDF 库,但两者都迫使你做出取舍。pdfplumber 擅长处理表格,却比必要速度慢 29 倍。PyMuPDF 速度很快,但被 AGPL-3.0 许可证束缚,阻碍了商业使用。本页对比两者,并说明为什么对大多数使用场景而言,PDF Oxide 是更好的选择

简短结论: PDF Oxide 比 pdfplumber 快 29 倍,比 PyMuPDF 快 5.8 倍,采用 MIT 许可证,并在同一个库中处理文本、图像、表单、加密、Markdown 输出和 OCR。pdfplumber 至今仍领先的唯一领域,是带可视化调试的复杂表格提取。

快速对比

pdfplumber PyMuPDF PDF Oxide
许可证 MIT AGPL-3.0 MIT
语言 纯 Python C(MuPDF) Rust + PyO3
平均提取时间 23.2ms 4.6ms 0.8ms
p99 提取时间 189ms 28ms 9ms
通过率(3,830 个 PDF) 98.8% 99.3% 100%
文本提取 支持 支持 支持
字符位置 支持 支持 支持
表格提取 高级 基础 基础
图像提取 不支持 支持 支持
可视化调试 支持 不支持 不支持
PDF 创建 不支持 支持 支持
PDF 编辑 不支持 支持 支持
Markdown 输出 不支持 不支持 支持
HTML 输出 不支持 不支持 支持
表单字段 仅读取 读取 + 写入 读取 + 写入
加密 不支持 读取 + 写入 读取 + 写入
渲染 不支持 支持 支持
OCR 不支持 Tesseract 内置(PaddleOCR)
安装体积 约 1 MB 约 20 MB 约 5 MB
Python 版本 3.8+ 3.8–3.12 3.8–3.14

速度基准测试

这三个库都在同一份语料库上进行基准测试,该语料库包含来自三个独立公开测试套件(veraPDF、Mozilla pdf.js、DARPA SafeDocs)的 3,830 个 PDF。语料库涵盖了所有 PDF 规范版本(1.0–2.0)、加密文件、格式错误的文档、CJK 编码以及复杂的版式。

指标 pdfplumber PyMuPDF PDF Oxide
平均提取时间 23.2ms 4.6ms 0.8ms
p99 提取时间 189ms 28ms 9ms
相对于 PDF Oxide 慢 29 倍 慢 5.8 倍 1 倍
通过率(有效 PDF) 98.8%(3,777/3,823) 99.3%(3,796/3,823) 100%(3,823/3,823)

PyMuPDF 大约比 pdfplumber 快 5 倍,因为它将所有解析工作委托给 MuPDF 的 C 库。pdfplumber 基于 pdfminer 进行解析,再叠加自己的空间分析层——两者都是用纯 Python 编写的。PDF Oxide 通过 PyO3 在 Python 进程中直接运行的编译后 Rust 代码,处理所有解析、字体解码和文本组装,这正是它相对 PyMuPDF 快 5.8 倍、相对 pdfplumber 快 29 倍的原因。

这些数字在实践中的意义

工作负载 pdfplumber PyMuPDF PDF Oxide
100 个 PDF 2.3 秒 0.46 秒 0.08 秒
1,000 个 PDF 23 秒 4.6 秒 0.8 秒
10,000 个 PDF 3.9 分钟 46 秒 8 秒
100,000 个 PDF 39 分钟 7.7 分钟 80 秒

对于处理少量文件的一次性脚本,速度差异无关紧要。但对于每天处理数千份文档的生产流水线,39 分钟与 80 秒之间的差距会影响架构决策。

表格提取

表格提取是开发者选择 pdfplumber 而非 PyMuPDF 的主要原因。这正是 pdfplumber 真正出色的地方。

pdfplumber:结构化表格解析

pdfplumber 提供专门的表格提取功能,支持可配置的线条检测、单元格合并和可视化调试:

import pdfplumber

with pdfplumber.open("invoice.pdf") as pdf:
    page = pdf.pages[0]

    # Extract all tables as structured data
    tables = page.extract_tables()
    for table in tables:
        for row in table:
            print(row)

    # Fine-tune detection with custom settings
    tables = page.extract_tables({
        "vertical_strategy": "text",
        "horizontal_strategy": "lines",
        "snap_tolerance": 5,
    })

    # Visual debugging: render page with detected table boundaries
    im = page.to_image()
    im.debug_tablefinder()
    im.save("debug.png")

pdfplumber 返回结构化的行/列数据,并能处理合并单元格、跨列表头和无边框表格。可视化调试叠加层在处理棘手版式、调整提取参数时极为宝贵。

PyMuPDF:基础表格检测

PyMuPDF 在近期版本中加入了表格检测,但它不如 pdfplumber 的算法成熟:

import fitz

doc = fitz.open("invoice.pdf")
page = doc[0]

# PyMuPDF's built-in table finder (added in v1.23)
tabs = page.find_tables()
for table in tabs:
    df = table.to_pandas()  # requires pandas
    print(df)

PyMuPDF 的表格提取适用于带可见边框的简单网格表格。但它在无边框版式、多级表头以及跨多行或多列的单元格上表现不佳——而这些恰恰是 pdfplumber 最擅长的场景。

PDF Oxide:Markdown 表格输出

PDF Oxide 在其结构化输出流水线中将表格转换为 Markdown 语法:

from pdf_oxide import PdfDocument

doc = PdfDocument("invoice.pdf")

# Tables are detected and converted to Markdown table format
md = doc.to_markdown(0, detect_headings=True)
print(md)

# Also available as HTML with table tags
html = doc.to_html(0)
print(html)

PDF Oxide 的表格检测对标准网格版式可用,并生成干净的 Markdown 或 HTML 输出。对于含合并单元格、无边框设计或跨列表头的复杂表格,pdfplumber 的专用算法仍然更为稳健。

表格提取小结

能力 pdfplumber PyMuPDF PDF Oxide
简单有边框表格 支持 支持 支持
无边框表格 支持 有限 有限
合并单元格 支持 有限 有限
多级表头 支持 不支持 不支持
可配置检测 支持 有限 不支持
可视化调试 支持 不支持 不支持
输出格式 Python 列表 pandas DataFrame Markdown / HTML
速度 慢(纯 Python) 最快

如果你唯一的使用场景就是复杂表格提取,pdfplumber 是最佳工具。如果你需要表格的同时还要快速文本提取、图像提取或 PDF 创建,PDF Oxide 覆盖的范围更广。

文本提取

对于纯文本提取,两个库都能完成任务,但在速度和 API 设计上有所不同。

pdfplumber

import pdfplumber

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

PyMuPDF

import fitz

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

PDF Oxide

from pdf_oxide import PdfDocument

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

对于格式良好的 PDF,三者都能产生相当的文本输出。在整个语料库上,PDF Oxide 与 PyMuPDF 的文本一致率达到 99.5%,剩余 0.5% 的差异在于空白归一化和连字处理。

字符级定位

pdfplumber 和 PyMuPDF 都提供字符级位置数据,这对于空间分析、边界框检测和自定义版式重建非常重要。

pdfplumber

import pdfplumber

with pdfplumber.open("report.pdf") as pdf:
    page = pdf.pages[0]
    for char in page.chars[:10]:
        print(f"'{char['text']}' at ({char['x0']:.1f}, {char['top']:.1f}) "
              f"size={char['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}")

PDF Oxide

from pdf_oxide import PdfDocument

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

pdfplumber 返回带丰富元数据的逐字符字典。PyMuPDF 返回嵌套的块/行/跨度结构。PDF Oxide 返回带位置和字体数据的扁平字符对象。

许可证

对于商业项目,这是 pdfplumber 与 PyMuPDF 之间最具影响力的区别。

pdfplumber PyMuPDF PDF Oxide
许可证 MIT AGPL-3.0 MIT
商业产品 可以 需要商业许可证 可以
闭源 SaaS 可以 需要商业许可证 可以
Docker 分发 可以 需要商业许可证 可以
内部工具 可以 可以 可以
开源项目 可以 可以(若与 AGPL 兼容) 可以

PyMuPDF 的 AGPL 问题

PyMuPDF 封装了采用 AGPL-3.0 许可证的 MuPDF。如果你分发包含 PyMuPDF 的软件——包括 SaaS、Web 应用和 Docker 容器——你的代码必须以 AGPL 开源,否则你必须向 Artifex 购买商业许可证。

Artifex 不公开商业许可证的定价。你必须联系其销售团队获取报价。许可证通常按应用计费,每年续订,没有免费层级,也没有面向初创公司的例外。

pdfplumber 和 PDF Oxide 都是 MIT

pdfplumber 和 PDF Oxide 都采用 MIT 许可证。在任何项目中使用任一者——商业、专有、SaaS 或开源——都没有义务约束。如果许可证是你的首要考量,并且你正在 pdfplumber 与 PyMuPDF 之间做选择,那么 pdfplumber(或 PDF Oxide)是更安全的选择。

加密 PDF

加密处理是 pdfplumber 功能集中的一大空白,也是处理受密码保护文档的开发者常见的痛点。

pdfplumber:不支持加密

pdfplumber 根本无法打开加密或受密码保护的 PDF。如果你将加密 PDF 传给 pdfplumber,它会抛出错误。你必须先用其他工具解密文件:

import pdfplumber

# This will fail on encrypted PDFs:
with pdfplumber.open("encrypted.pdf") as pdf:
    # raises pdfminer.pdfparser.PDFSyntaxError or similar
    pass

常见的变通做法是先用 PyMuPDF 或 pypdf 解密文件,再传给 pdfplumber 进行表格提取——这会给你的流水线增加又一个依赖。

PyMuPDF:完整加密支持

import fitz

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

PyMuPDF 同时支持用户密码和所有者密码、AES-128 和 AES-256 加密,并且能够创建加密 PDF。

PDF Oxide:完整加密支持

from pdf_oxide import PdfDocument

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

PDF Oxide 在读取和写入两方面都能处理所有标准 PDF 加密方法(RC4、AES-128、AES-256)。无需额外依赖或预处理。

图像提取

这是 pdfplumber 功能集中的另一处空白。pdfplumber 不会从 PDF 中提取嵌入的图像。

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

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

如果你的流水线需要从 PDF 中同时提取文本和图像,pdfplumber 无法处理图像这一部分。为此你需要 PyMuPDF、PDF Oxide 或 pypdfium2。

Markdown 和 HTML 输出

pdfplumber 和 PyMuPDF 都不提供内置的 Markdown 或 HTML 转换。这是 PDF Oxide 独有的功能。

from pdf_oxide import PdfDocument

doc = PdfDocument("paper.pdf")

# Markdown with heading detection and table formatting
md = doc.to_markdown(0, detect_headings=True)
print(md)

# HTML with semantic tags
html = doc.to_html(0)
print(html)

对于 LLM 流水线、RAG 系统和文档转换工作流,结构化的 Markdown 输出免去了单独的转换步骤。PyMuPDF 用户通常依赖独立的 pymupdf4llm 包,而它比 PDF Oxide 的内置转换慢 69 倍。

何时选择哪个库

在以下情况选择 pdfplumber:

  • 复杂表格提取是你的主要使用场景。 pdfplumber 的表格算法在处理合并单元格、无边框表格和跨列表头方面优于任何其他 Python 库。
  • 你需要可视化调试。 pdfplumber 能够渲染带注释的页面图像,展示检测到的线条、字符和表格边界——这在调整棘手文档的提取时极为宝贵。
  • 你想要纯 Python 方案。 没有编译依赖,凡是能运行 Python 的地方都能安装。
  • 速度不是问题。 如果你每次处理少于一百个文件,平均 23ms 完全可以接受。

在以下情况选择 PyMuPDF:

  • 你已经拥有商业 MuPDF 许可证,并依赖 MuPDF 特有的渲染或 SVG 导出。
  • 你需要高保真渲染。 MuPDF 的渲染引擎成熟,能很好地处理复杂 PDF。
  • 你的项目与 AGPL 兼容。 如果你在 AGPL 或兼容许可证下构建开源软件,PyMuPDF 的许可证不成问题。
  • 你需要通过 Tesseract 进行 OCR。 PyMuPDF 内置了针对扫描文档的 Tesseract 集成。

在以下情况选择 PDF Oxide:

  • 你既要速度又要广泛的功能覆盖。 平均 0.8ms 提取——比 PyMuPDF 快 5.8 倍,比 pdfplumber 快 29 倍——并在一个库中提供文本、图像、表单、创建和加密。
  • 你想要 MIT 许可证而不牺牲速度。 pdfplumber 是 MIT 但慢。PyMuPDF 快但是 AGPL。PDF Oxide 既是 MIT 又快。
  • 你需要 Markdown 或 HTML 输出。 面向 LLM 流水线和 RAG 系统的内置结构化转换。
  • 你需要在宽松许可证下支持加密 PDF。 pdfplumber 无法处理加密。PyMuPDF 可以,但需要遵守 AGPL。PDF Oxide 在 MIT 下处理加密。
  • 你想要一个库完成提取、创建和编辑。 pdfplumber 和 PyMuPDF 都需要额外工具来完成 PDF 工作流的某些部分。PDF Oxide 覆盖提取、创建、编辑、渲染和校验。

同时使用 PDF Oxide + pdfplumber:

对于既需要快速文本提取、图像提取,又需要复杂表格解析的流水线,可以用 PDF Oxide 处理通用流水线,用 pdfplumber 处理表格:

from pdf_oxide import PdfDocument
import pdfplumber

# Fast text and image extraction with PDF Oxide
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
images = doc.extract_images(0)

# Complex table extraction with pdfplumber
with pdfplumber.open("report.pdf") as pdf:
    tables = pdf.pages[0].extract_tables()

安装

# pdfplumber
pip install pdfplumber

# PyMuPDF
pip install pymupdf

# PDF Oxide
pip install pdf_oxide

三者都通过 pip 安装。pdfplumber 和 PDF Oxide 采用 MIT 许可证。PyMuPDF 是 AGPL-3.0——在将其加入商业项目前,请审查其许可证影响。

结论

pdfplumber 和 PyMuPDF 都只解决了问题的一部分。PDF Oxide 解决了整个问题。

你最看重什么 最佳选择
极致速度 PDF Oxide(0.8ms——比 pdfplumber 快 29 倍)
复杂表格提取 pdfplumber(可视化调试、合并单元格)
宽松许可证 + 速度 PDF Oxide——pdfplumber 是 MIT 但慢,PyMuPDF 快但是 AGPL
加密 PDF PDF Oxide 或 PyMuPDF——pdfplumber 无法解密
图像提取 PDF Oxide 或 PyMuPDF——pdfplumber 不支持图像
Markdown/HTML 输出 PDF Oxide——唯一内置转换的库
无需 Tesseract 的 OCR PDF Oxide——内置 PaddleOCR
一个库搞定一切 PDF Oxide——提取、创建、编辑、加密、OCR

除非你的整个工作流都是复杂表格提取(无边框表格、合并单元格、可视化调试),否则PDF Oxide 可以取代 pdfplumber 和 PyMuPDF——更快、功能更多、采用 MIT 许可证。

10 秒上手:

pip install pdf_oxide
from pdf_oxide import PdfDocument

doc = PdfDocument("report.pdf")
text = doc.extract_text(0)       # 29× faster than pdfplumber
md = doc.to_markdown(0)          # built-in, no separate package
images = doc.extract_images(0)   # pdfplumber can't do this

相关页面