Миграция с PyMuPDF (fitz) на PDF Oxide
Полное руководство по переходу с PyMuPDF на PDF Oxide: все API, которыми вы пользуетесь сегодня, и их замены.
Зачем уходить с PyMuPDF?
Четыре веские причины для миграции:
- В 5,8× быстрее — PDF Oxide в среднем обрабатывает страницу за 0,8 мс против 4,6 мс у PyMuPDF. На объёме разница накапливается: пакет из 1 000 страниц завершается меньше чем за секунду, а не за пять.
- Лицензия MIT — PyMuPDF распространяется под AGPL, которая обязывает открывать исходники любого кода, взаимодействующего с ней, или покупать коммерческую лицензию. PDF Oxide под MIT — применяйте где угодно без оговорок.
- Надёжность 100 % — PDF Oxide проходит 100 % тестового набора PDF. PyMuPDF срывается на 0,7 % файлов (99,3 % успеха) — это примерно один сломанный результат на каждые 140 документов.
- Функции «из коробки» — конвертация в Markdown, вывод HTML, OCR, поддержка XFA-форм и рендеринг PDF включены. PyMuPDF для того же требует отдельные пакеты (
pymupdf4llm) или внешние инструменты (Tesseract).
Шаг 1. Установка
pip install pdf_oxide
pip uninstall pymupdf # опционально — удалите, когда будете готовы
Шаг 2. Замените импорты
# До
import fitz
# После
from pdf_oxide import PdfDocument
Если для Markdown использовался pymupdf4llm, эту зависимость можно полностью убрать — PDF Oxide поддерживает Markdown нативно.
Шаг 3. Таблица соответствия API
| Задача | PyMuPDF | PDF Oxide |
|---|---|---|
| Открыть PDF | fitz.open("file.pdf") |
PdfDocument("file.pdf") |
| Количество страниц | doc.page_count |
doc.page_count() |
| Извлечь текст | doc[0].get_text() |
doc.extract_text(0) |
| Позиции символов | doc[0].get_text("dict") |
doc.extract_chars(0) |
| Извлечь изображения | doc[0].get_images() + doc.extract_image(xref) |
doc.extract_images(0) |
| Поиск текста | doc[0].search_for("query") |
doc.search_page(0, "query") |
| Поля форм | doc[0].widgets() или doc.get_form_fields() |
doc.get_form_fields() |
| Зашифрованный PDF | doc.authenticate("pw") |
PdfDocument("f.pdf", password="pw") |
| В Markdown | pymupdf4llm.to_markdown("file.pdf") (отдельный пакет) |
doc.to_markdown(0) (встроено) |
| В HTML | Недоступно | doc.to_html(0) |
| Создать PDF | Ручной insert_text() |
Pdf.from_markdown("# Заголовок") |
| Рендер в изображение | doc[0].get_pixmap() |
doc.render_page(0) |
| XFA-формы | Не поддерживаются | doc.has_xfa() |
| OCR | Требуется Tesseract | Встроенный PaddleOCR |
Шаг 4. Типичные изменения паттернов
Цикл извлечения текста
# PyMuPDF
import fitz
doc = fitz.open("report.pdf")
for page in doc:
text = page.get_text()
print(text)
# PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
for i in range(doc.page_count()):
text = doc.extract_text(i)
print(text)
Извлечение изображений
PyMuPDF требует многошагового обхода через xref. PDF Oxide делает это за один вызов:
# PyMuPDF — многошаговый поиск через xref
import fitz
doc = fitz.open("report.pdf")
page = doc[0]
for img in page.get_images():
xref = img[0]
base = doc.extract_image(xref)
with open(f"img.{base['ext']}", "wb") as f:
f.write(base["image"])
# PDF Oxide — один шаг
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
for i, img in enumerate(doc.extract_image_bytes(0)):
with open(f"img_{i}.{img['format']}", "wb") as f:
f.write(img["data"])
Зашифрованные PDF
В PyMuPDF принят двухшаговый паттерн «открыть, затем аутентифицироваться». PDF Oxide поддерживает и password= в конструкторе, и вызов doc.authenticate() после открытия:
# PyMuPDF
import fitz
doc = fitz.open("encrypted.pdf")
doc.authenticate("password")
text = doc[0].get_text()
# PDF Oxide — один шаг с password=
from pdf_oxide import PdfDocument
doc = PdfDocument("encrypted.pdf", password="password")
text = doc.extract_text(0)
Конвертация в Markdown
PyMuPDF требует отдельный пакет pymupdf4llm. В PDF Oxide Markdown встроен:
# PyMuPDF — нужен дополнительный пакет
import pymupdf4llm
md = pymupdf4llm.to_markdown("report.pdf")
# PDF Oxide — встроено
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
md = doc.to_markdown(0)
Рендеринг страниц
# PyMuPDF
import fitz
doc = fitz.open("report.pdf")
pix = doc[0].get_pixmap()
pix.save("page.png")
# PDF Oxide
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
png_bytes = doc.render_page(0, dpi=150)
with open("page.png", "wb") as f:
f.write(png_bytes)
Шаг 5. Проверка миграции
Прогоните свои тестовые файлы через обе библиотеки и сравните вывод:
from pdf_oxide import PdfDocument
doc = PdfDocument("your-test-file.pdf")
# Проверка извлечения текста
text = doc.extract_text(0)
print(text[:500])
# Проверка количества страниц
print(f"Pages: {doc.page_count()}")
# Проверка полей форм (если есть)
fields = doc.get_form_fields()
for f in fields:
print(f"{f.name}: {f.value}")
Другие руководства по миграции
Связанные страницы
- PDF Oxide vs PyMuPDF — подробное сравнение
- Начало работы с Python — установка
- Извлечение текста из PDF — руководство по извлечению текста