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 做不到
相关页面
- PDF Oxide vs PyMuPDF – 含迁移指南的详细对比
- PDF Oxide vs pdfplumber – 含代码示例的详细对比
- vs Python PDF 库 – 所有 Python 库对比
- 性能基准测试 – 完整语料库基准测试方法
- 从 PDF 提取表格 – 表格提取指南
- Python 快速入门 – 安装和首次提取