Skip to content

pdfplumber vs PyMuPDF — скорость, таблицы и лицензирование

pdfplumber и PyMuPDF — популярные Python-библиотеки для работы с PDF, но обе вынуждают идти на компромиссы. pdfplumber отлично справляется с таблицами, но в 29 раз медленнее, чем необходимо. PyMuPDF быстра, но скована лицензией AGPL-3.0, которая блокирует коммерческое использование. Эта страница сравнивает обе библиотеки и показывает, почему PDF Oxide — лучший выбор для большинства сценариев.

Короткий ответ: PDF Oxide в 29 раз быстрее pdfplumber, в 5,8 раза быстрее PyMuPDF, имеет лицензию 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

Бенчмарки скорости

Все три библиотеки протестированы на одном и том же корпусе из 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 примерно в 5 раз быстрее pdfplumber, потому что делегирует весь разбор C-библиотеке MuPDF. pdfplumber использует pdfminer для разбора, а затем добавляет собственный слой пространственного анализа — оба написаны на чистом Python. PDF Oxide выполняет весь разбор, декодирование шрифтов и сборку текста в скомпилированном Rust, работающем прямо в процессе Python через PyO3, что и обеспечивает её преимущество в 5,8 раза над PyMuPDF и в 29 раз над pdfplumber.

Что эти цифры значат на практике

Нагрузка 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 DataFrame pandas 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 достигает 99,5% совпадения текста с PyMuPDF на всём корпусе, а оставшиеся 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) Да

Проблема AGPL у PyMuPDF

PyMuPDF оборачивает MuPDF, который лицензирован под AGPL-3.0. Если вы распространяете ПО, включающее PyMuPDF, — в том числе SaaS, веб-приложения и 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, который в 69 раз медленнее встроенного преобразования PDF Oxide.

Когда выбирать каждую библиотеку

Выбирайте pdfplumber, если:

  • Извлечение сложных таблиц — ваш основной сценарий. Алгоритмы таблиц pdfplumber обрабатывают объединённые ячейки, таблицы без рамок и охватывающие заголовки лучше любой другой Python-библиотеки.
  • Вам нужна визуальная отладка. pdfplumber может рендерить размеченные изображения страниц, показывающие распознанные линии, символы и границы таблиц, — это незаменимо для настройки извлечения на сложных документах.
  • Вам нужно решение на чистом Python. Никаких скомпилированных зависимостей, устанавливается везде, где работает Python.
  • Скорость не важна. Если вы обрабатываете менее сотни файлов за раз, среднее значение 23ms вполне приемлемо.

Выбирайте PyMuPDF, если:

  • У вас уже есть коммерческая лицензия MuPDF и вы зависите от специфичного для MuPDF рендеринга или экспорта в SVG.
  • Вам нужен высококачественный рендеринг. Движок рендеринга MuPDF зрелый и хорошо справляется со сложными PDF.
  • Ваш проект совместим с AGPL. Если вы создаёте ПО с открытым кодом под AGPL или совместимой лицензией, лицензирование PyMuPDF не проблема.
  • Вам нужен OCR через Tesseract. PyMuPDF имеет встроенную интеграцию с Tesseract для отсканированных документов.

Выбирайте PDF Oxide, если:

  • Вам нужны скорость и широкий набор функций. Среднее извлечение 0,8ms — в 5,8 раза быстрее PyMuPDF, в 29 раз быстрее pdfplumber — с текстом, изображениями, формами, созданием и шифрованием в одной библиотеке.
  • Вы хотите лицензию 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 — в 29 раз быстрее pdfplumber)
Извлечение сложных таблиц pdfplumber (визуальная отладка, объединённые ячейки)
Разрешительная лицензия + скорость PDF Oxide — pdfplumber MIT, но медленная, PyMuPDF быстрая, но AGPL
Зашифрованные PDF PDF Oxide или PyMuPDF — pdfplumber не умеет расшифровывать
Извлечение изображений PDF Oxide или PyMuPDF — у pdfplumber нет поддержки изображений
Вывод в Markdown/HTML PDF Oxide — единственная библиотека со встроенным преобразованием
OCR без Tesseract 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

Связанные страницы