Сравнение с Python-библиотеками для PDF
PDF Oxide в сравнении с PyMuPDF (fitz), pypdfium2, pypdf, pdfplumber, pdfminer и другими. На этой странице разбираются производительность, охват функций, лицензирование и различия в API, чтобы помочь вам выбрать подходящую Python-библиотеку для извлечения текста из PDF.
Кратко
| PDF Oxide | PyMuPDF | pypdfium2 | pypdf | pdfplumber | pdfminer | |
|---|---|---|---|---|---|---|
| Среднее время извлечения | 0.8ms | 4.6ms | 4.1ms | 12.1ms | 23.2ms | 16.8ms |
| Доля успеха (3830 PDF) | 100% | 99.3% | 99.2% | 98.4% | 98.8% | 98.8% |
| Лицензия | MIT | AGPL-3.0 | Apache-2.0 | BSD-3 | MIT | MIT |
| Язык | Rust + PyO3 | C (MuPDF) | C (PDFium) | Pure Python | Pure Python | Pure Python |
| Извлечение текста | Да | Да | Да | Да | Да | Да |
| Позиции символов | Да | Да | Да | Частично | Да | Да |
| Извлечение изображений | Да | Да | Да | Да | Нет | Нет |
| Поля форм | Чтение + запись | Чтение + запись | Только чтение | Чтение + запись | Только чтение | Нет |
| Создание PDF | Да | Да | Нет | Ограниченно | Нет | Нет |
| Редактирование PDF | Да | Да | Нет | Да | Нет | Нет |
| Вывод в Markdown | Да | Нет | Нет | Нет | Нет | Нет |
| Вывод в HTML | Да | Нет | Нет | Нет | Нет | Нет |
| Шифрование | Чтение + запись | Чтение + запись | Только чтение | Чтение + запись | Нет | Нет |
| Проверка PDF/A | Да | Нет | Нет | Нет | Нет | Нет |
| Рендеринг | Да | Да | Да | Нет | Нет | Нет |
| Поиск | Regex + пространственный | Да | Да | Нет | Нет | Нет |
| Версии Python | 3.8–3.14 | 3.8–3.12 | 3.8+ | 3.6+ | 3.8+ | 3.6+ |
| Размер установки | ~5 МБ wheel | ~20 МБ wheel | ~3 МБ wheel | ~1 МБ | ~1 МБ | ~1 МБ |
Сравнение производительности
Среднее время извлечения текста на один PDF, измеренное на полном корпусе из 3830 PDF — это три независимых, общедоступных набора тестов, которые вместе охватывают все версии спецификации PDF (1.0–2.0), зашифрованные файлы, некорректные документы, CJK-кодировки, сложные макеты и пограничные случаи безопасности. О том, что тестирует каждый набор и почему эти результаты воспроизводимы, см. подробности о корпусе.
| Библиотека | Среднее | Относит. | p99 | Доля успеха |
|---|---|---|---|---|
| PDF Oxide | 0.8ms | 1× | 9ms | 100% |
| PyMuPDF | 4.6ms | 5.8× | 28ms | 99.3% |
| pypdfium2 | 4.1ms | 5.1× | 42ms | 99.2% |
| pymupdf4llm | 55.5ms | 69× | 280ms | 99.1% |
| pdftext | 7.3ms | 9.1× | 82ms | 99.0% |
| pdfminer | 16.8ms | 21× | 124ms | 98.8% |
| pdfplumber | 23.2ms | 29× | 189ms | 98.8% |
| markitdown | 108.8ms | 136× | 378ms | 98.6% |
| pypdf | 12.1ms | 15.1× | 97ms | 98.4% |
PDF Oxide достигает такой скорости благодаря нативному ядру на Rust, скомпилированному в модуль расширения Python через PyO3. Нет накладных расходов на подпроцессы или мостов к C-библиотекам — код на Rust выполняется прямо в процессе Python.
Надёжность
PDF Oxide обрабатывает 3823 из 3823 валидных PDF без сбоев — доля успеха 100%. Те 7 файлов из корпуса в 3830 документов, что не прошли проверку, — это намеренно повреждённые тестовые образцы (отсутствующий заголовок PDF, повреждённые фаззингом каталоги, некорректные xref-потоки).
| Библиотека | Прошло валидных PDF | Доля успеха |
|---|---|---|
| PDF Oxide | 3,823 / 3,823 | 100% |
| PyMuPDF | 3,796 / 3,823 | 99.3% |
| pypdfium2 | 3,792 / 3,823 | 99.2% |
| pymupdf4llm | 3,787 / 3,823 | 99.1% |
| pdftext | 3,784 / 3,823 | 99.0% |
| pdfminer | 3,777 / 3,823 | 98.8% |
| pdfplumber | 3,777 / 3,823 | 98.8% |
| markitdown | 3,771 / 3,823 | 98.6% |
| pypdf | 3,762 / 3,823 | 98.4% |
Качество текста
PDF Oxide достигает 99.5% совпадения текста по сравнению с PyMuPDF и pypdfium2 на всём корпусе. Качество измерялось посимвольным сравнением извлечённого текста. Оставшиеся 0.5% различий приходятся на нормализацию пробелов и обработку лигатур, где PDF Oxide выдаёт более чистый результат.
Сравнение лицензий
| Библиотека | Лицензия | Коммерческое использование | Copyleft |
|---|---|---|---|
| PDF Oxide | MIT | Без ограничений | Нет |
| pypdfium2 | Apache-2.0 | Без ограничений | Нет |
| PyMuPDF | AGPL-3.0 | Требуется коммерческая лицензия ($) | Да |
| pypdf | BSD-3 | Без ограничений | Нет |
| pdfplumber | MIT | Без ограничений | Нет |
| pdfminer | MIT | Без ограничений | Нет |
| pdftext | GPL-3.0 | Требует открытого кода | Да |
PyMuPDF использует MuPDF под лицензией AGPL-3.0. Если вы распространяете программу, использующую PyMuPDF, ваша программа тоже должна быть выпущена под AGPL-3.0 — либо вам нужно приобрести коммерческую лицензию у Artifex. Это касается SaaS-продуктов, веб-приложений и любых распространяемых бинарных файлов.
PDF Oxide распространяется под лицензией MIT без каких-либо ограничений. Используйте его в проприетарных продуктах, SaaS-платформах или приложениях с закрытым кодом без каких-либо лицензионных обязательств.
| Сценарий | PDF Oxide (MIT) | PyMuPDF (AGPL) | pypdfium2 (Apache) | pypdf (BSD) | pdfplumber (MIT) | pdfminer (MIT) |
|---|---|---|---|---|---|---|
| Коммерческий продукт | Да | Нужна лицензия | Да | Да | Да | Да |
| Закрытый код | Да | Нет (без лицензии) | Да | Да | Да | Да |
| SaaS/облако | Да | Нужна лицензия | Да | Да | Да | Да |
| Внутренние инструменты | Да | Да | Да | Да | Да | Да |
Сравнение API
Извлечение текста
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)
PyMuPDF:
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
text = page.get_text()
print(text)
pypdf:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
page = reader.pages[0]
text = page.extract_text()
print(text)
pdfplumber:
import pdfplumber
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[0]
text = page.extract_text()
print(text)
pdfminer:
from pdfminer.high_level import extract_text
text = extract_text("report.pdf", page_numbers=[0])
print(text)
Извлечение на уровне символов
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
chars = doc.extract_chars(0)
for ch in chars:
print(f"'{ch.char}' at ({ch.bbox[0]:.1f}, {ch.bbox[1]:.1f}) "
f"size={ch.font_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}")
pdfplumber:
import pdfplumber
with pdfplumber.open("report.pdf") as pdf:
page = pdf.pages[0]
for char in page.chars:
print(f"'{char['text']}' at ({char['x0']:.1f}, {char['top']:.1f}) "
f"size={char['size']:.1f}")
pdfminer:
from pdfminer.high_level import extract_pages
from pdfminer.layout import LTChar
for page_layout in extract_pages("report.pdf"):
for element in page_layout:
if hasattr(element, '__iter__'):
for text_line in element:
if hasattr(text_line, '__iter__'):
for char in text_line:
if isinstance(char, LTChar):
print(f"'{char.get_text()}' at ({char.x0:.1f}, {char.y0:.1f}) "
f"size={char.size:.1f}")
Извлечение изображений
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"])
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"])
pypdf:
from pypdf import PdfReader
reader = PdfReader("report.pdf")
page = reader.pages[0]
for i, image in enumerate(page.images):
with open(f"image_{i}.{image.name.split('.')[-1]}", "wb") as f:
f.write(image.data)
Создание PDF
PDF Oxide:
from pdf_oxide import Pdf
pdf = Pdf.from_markdown("# Hello World\n\nThis is a PDF.")
pdf.save("output.pdf")
# Also supports HTML
pdf = Pdf.from_html("<h1>Hello</h1><p>World</p>")
pdf.save("output.pdf")
PyMuPDF:
import fitz
doc = fitz.open()
page = doc.new_page()
text_point = fitz.Point(72, 72)
page.insert_text(text_point, "Hello World", fontsize=24)
doc.save("output.pdf")
pypdf:
# pypdf can merge/modify PDFs but cannot create from scratch with text content.
# Use reportlab or fpdf2 for creation, then merge with pypdf.
Зашифрованные PDF
PDF Oxide:
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)
PyMuPDF:
import fitz
doc = fitz.open("encrypted.pdf")
doc.authenticate("password")
page = doc[0]
text = page.get_text()
pypdf:
from pypdf import PdfReader
reader = PdfReader("encrypted.pdf")
reader.decrypt("password")
text = reader.pages[0].extract_text()
Вывод в Markdown и HTML
PDF Oxide (уникальная возможность):
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
# Convert to Markdown with heading detection
md = doc.to_markdown(0, detect_headings=True)
print(md)
# Convert to HTML
html = doc.to_html(0)
print(html)
Ни одна другая Python-библиотека для PDF не предоставляет встроенного преобразования в Markdown или HTML.
Профили библиотек
PDF Oxide
Сильные стороны:
- Самое быстрое извлечение текста в бенчмарках благодаря ядру на Rust — в 5.8 раза быстрее PyMuPDF
- 100% успешных тестов на корпусе из 3830 PDF — наивысшая надёжность среди всех протестированных библиотек
- Единый API для извлечения, создания и редактирования в одной библиотеке
- Встроенный экспорт в Markdown и HTML с распознаванием заголовков
- Лицензия MIT без copyleft-ограничений
- Нативная проверка соответствия (PDF/A, PDF/UA, PDF/X)
- Готовые wheel-пакеты для всех основных платформ и Python 3.8–3.14
- Нет системных зависимостей — wheel содержит всё необходимое
Ограничения:
- Более молодая библиотека с меньшим сообществом
- Извлечение таблиц базовое по сравнению с алгоритмами pdfplumber
- Движок рендеринга менее зрелый, чем MuPDF
PyMuPDF (fitz)
Сильные стороны:
- Зрелая и проверенная временем (на основе MuPDF, в разработке с 2005 года)
- Отличное качество рендеринга сложных PDF
- Встроенная интеграция OCR (Tesseract)
- Богатый набор функций: экспорт в SVG, манипуляции со страницами, обнаружение таблиц
Ограничения:
- Лицензия AGPL-3.0 требует открыть код вашего приложения или приобрести коммерческую лицензию
- Большой размер wheel (~20 МБ) из-за встроенного MuPDF
- Нет встроенного экспорта в Markdown
- Нет проверки соответствия
pypdfium2
Сильные стороны:
- Быстрый (на основе движка PDFium от Google)
- Лицензия Apache-2.0 — разрешительная для коммерческого использования
- Хорошее качество рендеринга
Ограничения:
- Ограниченный API извлечения текста по сравнению с PDF Oxide или PyMuPDF
- Нет создания или редактирования PDF
- Поддержка полей форм только для чтения
pypdf
Сильные стороны:
- Pure Python — устанавливается где угодно, без скомпилированных зависимостей
- Лёгкая и хорошо поддерживаемая
- Подходит для манипуляций с PDF (объединение, разделение, поворот, шифрование)
- Большое сообщество и обширная документация
Ограничения:
- В 15 раз медленнее PDF Oxide при извлечении текста
- Качество извлечения текста страдает на сложных макетах
- Нет рендеринга, экспорта в Markdown/HTML, извлечения таблиц
pdfplumber
Сильные стороны:
- Лучшее извлечение таблиц среди всех Python-библиотек для PDF
- Отличные данные о позиционировании на уровне символов
- Инструменты визуальной отладки (аннотированные изображения страниц)
- Лицензия MIT
Ограничения:
- Pure Python — в 29 раз медленнее PDF Oxide
- Только чтение — нет создания или редактирования PDF
- Нет шифрования или рендеринга
pdfminer
Сильные стороны:
- Детальный анализ символов и макета
- Хорошая поддержка CJK-текста
- Основа для pdfplumber и других инструментов
- Лицензия MIT
Ограничения:
- В 21 раз медленнее PDF Oxide (Pure Python, без оптимизаций)
- Только чтение, нет создания или редактирования
- Многословный API для типичных задач
- Поддерживается менее активно
Когда что использовать
| Сценарий | Рекомендуемая библиотека |
|---|---|
| Быстрое извлечение текста | PDF Oxide |
| Коммерческий / проприетарный продукт | PDF Oxide, pypdfium2, pypdf, pdfplumber или pdfminer |
| Альтернатива PyMuPDF (лицензия MIT) | PDF Oxide |
| Создание PDF из Markdown/HTML | PDF Oxide |
| Проверка соответствия (PDF/A, PDF/X) | PDF Oxide |
| Извлечение таблиц из счетов | pdfplumber |
| Визуальная отладка извлечения | pdfplumber |
| Уже вложились в MuPDF | PyMuPDF (если совместимо с AGPL) |
| Минимум зависимостей | pypdf (Pure Python) |
| Детальный анализ макета | pdfminer |
| OCR для отсканированных документов | PyMuPDF |
Установка
# PDF Oxide
pip install pdf_oxide
# PyMuPDF
pip install pymupdf
# pypdfium2
pip install pypdfium2
# pypdf
pip install pypdf
# pdfplumber
pip install pdfplumber
# pdfminer
pip install pdfminer.six
PDF Oxide поставляет готовые wheel-пакеты для Linux (x86_64, aarch64), macOS (x86_64, arm64) и Windows (x86_64). Компилятор и системные библиотеки не требуются.
Связанные страницы
- Бенчмарки производительности – результаты бенчмарков на полном корпусе
- Начало работы с Python – установка и первое извлечение
- Справочник по Python API – полный Python API
- Сравнение с Rust-библиотеками для PDF – сравнение экосистемы Rust