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
底层语言 Pure 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

速度基准测试

三个库都在相同的 3,830 个 PDF 语料库上进行了测试,来自三个独立的公开测试集(veraPDF、Mozilla pdf.js、DARPA SafeDocs)。语料库覆盖所有 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 倍 1x
通过率(有效 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 在 Python 进程中通过 PyO3 直接运行编译好的 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]

    # 提取所有表格为结构化数据
    tables = page.extract_tables()
    for table in tables:
        for row in table:
            print(row)

    # 使用自定义设置微调检测
    tables = page.extract_tables({
        "vertical_strategy": "text",
        "horizontal_strategy": "lines",
        "snap_tolerance": 5,
    })

    # 可视化调试:渲染带有检测到的表格边界的页面图片
    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 内置表格查找器(v1.23 新增)
tabs = page.find_tables()
for table in tabs:
    df = table.to_pandas()  # 需要 pandas
    print(df)

PyMuPDF 的表格提取适用于有可见边框的简单网格表格。对于无边框布局、多级表头以及跨行跨列的单元格——恰恰是 pdfplumber 最擅长的场景——它表现不佳。

PDF Oxide:Markdown 表格输出

PDF Oxide 将表格作为结构化输出流水线的一部分转换为 Markdown 语法:

from pdf_oxide import PdfDocument

doc = PdfDocument("invoice.pdf")

# 表格被检测并转换为 Markdown 表格格式
md = doc.to_markdown(0, detect_headings=True)
print(md)

# 也可以获取带有 table 标签的 HTML
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 返回嵌套的块/行/span 结构。PDF Oxide 返回扁平的字符对象,包含位置和字体数据。

许可证

这是 pdfplumber 和 PyMuPDF 在商业项目中最关键的差异。

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

PyMuPDF 的 AGPL 问题

PyMuPDF 封装的是 MuPDF,后者采用 AGPL-3.0 许可。如果你分发包含 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,它会抛出错误。你必须先用其他工具解密文件:

import pdfplumber

# 对加密 PDF 会失败:
with pdfplumber.open("encrypted.pdf") as pdf:
    # 抛出 pdfminer.pdfparser.PDFSyntaxError 或类似异常
    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 的另一个功能缺口——它不支持从 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
md = doc.to_markdown(0, detect_headings=True)
print(md)

# 带语义标签的 HTML
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

# 用 PDF Oxide 做快速文本和图片提取
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
images = doc.extract_image_bytes(0)

# 用 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)       # 比 pdfplumber 快 29 倍
md = doc.to_markdown(0)          # 内置,无需独立包
images = doc.extract_image_bytes(0)   # pdfplumber 做不到

相关页面