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.2 мс 4.6 мс 0.8 мс
Время извлечения p99 189 мс 28 мс 9 мс
Успешность (3,830 PDF) 98.8% 99.3% 100%
Извлечение текста Да Да Да
Позиции символов Да Да Да
Извлечение таблиц Продвинутое Базовое Базовое
Извлечение изображений Нет Да Да
Визуальная отладка Да Нет Нет
Создание PDF Нет Да Да
Редактирование PDF Нет Да Да
Вывод в Markdown Нет Нет Да
Вывод в HTML Нет Нет Да
Поля форм Только чтение Чтение + запись Чтение + запись
Шифрование Нет Чтение + запись Чтение + запись
Рендеринг Нет Да Да
OCR Нет Tesseract Встроенный (PaddleOCR)
Размер при установке ~1 МБ ~20 МБ ~5 МБ
Версии 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.2 мс 4.6 мс 0.8 мс
Время извлечения p99 189 мс 28 мс 9 мс
Относительно 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 секунд

Для одноразовых скриптов, обрабатывающих несколько файлов, разница в скорости несущественна. Для production-пайплайнов, обрабатывающих тысячи документов ежедневно, разрыв между 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)

# Также доступно как HTML с тегами таблиц
html = doc.to_html(0)
print(html)

Определение таблиц в PDF Oxide работает для стандартных сеточных макетов и выдаёт чистый Markdown или HTML. Для сложных таблиц с объединёнными ячейками, безрамочных макетов или перекрывающих заголовков специализированные алгоритмы pdfplumber по-прежнему надёжнее.

Итог по извлечению таблиц

Возможность pdfplumber PyMuPDF PDF Oxide
Простые таблицы с рамками Да Да Да
Безрамочные таблицы Да Ограниченно Ограниченно
Объединённые ячейки Да Ограниченно Ограниченно
Многоуровневые заголовки Да Нет Нет
Настраиваемое определение Да Ограниченно Нет
Визуальная отладка Да Нет Нет
Формат вывода Списки Python DataFrames 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 предоставляют данные о позициях символов, что важно для пространственного анализа, определения bounding box и восстановления макета.

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 Да Требуется коммерческая лицензия Да
Внутренние инструменты Да Да Да
Open-source проект Да Да (если совместим с AGPL) Да

Проблема AGPL у PyMuPDF

PyMuPDF оборачивает MuPDF, распространяемый под AGPL-3.0. Если вы распространяете ПО, включающее PyMuPDF — в том числе SaaS, веб-приложения и Docker-контейнеры — ваш код должен быть открыт под AGPL, либо вам нужно приобрести коммерческую лицензию у Artifex.

Artifex не публикует стоимость коммерческой лицензии. Нужно обращаться в отдел продаж. Лицензии обычно привязаны к приложению, продлеваются ежегодно, без бесплатного уровня или исключений для стартапов.

pdfplumber и PDF Oxide — оба под MIT

И pdfplumber, и PDF Oxide распространяются под лицензией MIT. Используйте любой из них в любом проекте — коммерческом, проприетарном, SaaS или open source — без обязательств. Если лицензирование — ваша основная забота и вы выбираете между pdfplumber и PyMuPDF, pdfplumber (или PDF Oxide) — более безопасный выбор.

Зашифрованные PDF

Обработка шифрования — существенный пробел в функциональности pdfplumber и частая проблема для разработчиков, работающих с защищёнными документами.

pdfplumber: нет поддержки шифрования

pdfplumber вообще не может открывать зашифрованные или защищённые паролем PDF. Передача зашифрованного PDF в pdfplumber приводит к ошибке. Файл нужно расшифровать заранее другим инструментом:

import pdfplumber

# На зашифрованных PDF вызовет ошибку:
with pdfplumber.open("encrypted.pdf") as pdf:
    # raises 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. 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, который в 69 раз медленнее встроенной конвертации PDF Oxide.

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

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

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

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

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

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

  • Нужна скорость и широкий охват функциональности. 0.8 мс среднее извлечение — в 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 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.8 мс — в 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 раз быстрее pdfplumber
md = doc.to_markdown(0)          # встроенное, без отдельного пакета
images = doc.extract_image_bytes(0)   # pdfplumber так не умеет

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