17.10.2026

PDF-парсеры: скорость, память и порядок чтения

19 библиотек, 230 документов, 10 400 страниц, около 33 тысяч замеров. По скорости лучшие движки идут вровень, решают сбои на битых файлах и то, как они собирают порядок чтения.

Выбор по операциям

Операция Брать Почему Запасной вариант
Текст PyMuPDF get_text() (mupdf-rs, если код на Rust) 330–425 страниц в секунду на ядро, 2 сбоя из 44 проблемных файлов, F1 0.974 и порядок 0.986 — на уровне лучших pypdfium2: на 10–20 % быстрее, 31 МБ против 157, но 8 сбоев из 44
Сигналы для OCR PyMuPDF в том же проходе единственный с полным набором сигналов, включая шрифты без ToUnicode; время ×2.5 к извлечению текста pypdfium2: ×1.6, без проверки ToUnicode
Таблицы PyMuPDF find_tables() 11 страниц в секунду, 0 сбоев, тот же движок pdfplumber: 10 страниц в секунду, меньше памяти
Изображения PyMuPDF extract_image() 24 страницы в секунду на сканах, 0 сбоев, JPEG и JPX без перекодирования pdfium-render: 52 страницы в секунду, но 8 сбоев
Рендер 200 DPI pypdfium2 4.9 страницы в секунду на ядро, 41 на 16 процессах, пик 271 МБ против 1246 у PyMuPDF PyMuPDF: 4.4 страницы в секунду, меньше сбоев

Извлечение текста

Скорость извлечения текста по библиотекам, страниц в секунду на одно ядро

Электронный текст, страниц в секунду на одно ядро (медиана трёх тёплых прогонов). Справа — сбои на 44 проблемных файлах.

Тройка лидеров по скорости — обёртки над pdfium и mupdf-rs, около 500 страниц в секунду. PyMuPDF чуть медленнее (425), но падает всего на 2 проблемных файлах из 44, а pdfium — на 8. На отчётности с таблицами разница исчезает: PyMuPDF 331 страница в секунду, pypdfium2 316.

Pure-Python парсеры (pypdf, pdfplumber, pdfminer.six) в 15–40 раз медленнее и падают чаще. pdf-rs показал 1366 страниц в секунду, но вне зачёта: декодер текста для него пришлось написать вручную, и он теряет 13–17 % символов.

Качество и порядок чтения

48 страниц из 30 документов: 16 статей arXiv (10 в две колонки) и 32 местных документа (отчётность с таблицами, прайсы, схемы). Эталон — распознавание отрисованной страницы моделью LightOnOCR-3, независимое от текстового слоя и проверенное глазами на 5 случайных страницах. Порядок — доля 4-грамм слов эталона, идущих в правильной последовательности.

Метод F1 по словам Порядок Порядок, 2 колонки Страниц в секунду
PyMuPDF get_text() 0.974 0.986 0.958 89
pdftotext (поток) 0.974 0.933 0.884 142
pdfminer 0.973 0.981 0.935 9
extractous 0.971 0.986 0.958 14
pypdfium2 0.966 0.986 0.958 142
pypdf 0.960 0.985 0.957 13
pymupdf4llm + layout 0.941 0.988 0.968 0.2
pymupdf4llm 0.895 0.992 0.986 6
pdfplumber 0.824 0.902 0.834 6
PyMuPDF sort=True 0.966 0.817 0.751 46
pdftotext -layout 0.966 0.814 0.748 149

Что из этого следует:

  • Порядок из потока PDF почти идеален. LaTeX и Word пишут текст в порядке чтения. Ошибки бывают, когда генератор писал блоки вразнобой: например, в прайс-листе нижняя таблица в файле идёт первой.
  • Сортировка по координатам вредит. sort=True и pdftotext -layout сшивают строки соседних колонок, порядок на двухколоночных страницах падает до 0.75.
  • pymupdf4llm лучше всех по порядку, но без разметки страницы выбрасывает текст внутри векторных схем, а с разметкой — формулы. И работает медленно: 6 и 0.2 страницы в секунду.
  • pypdfium2 отстаёт на 0.01 F1 только из-за переносов: перенос в конце строки он отдаёт служебным символом, и слово не склеивается. Это чинится одной заменой.

Таблицы

41 документ отчётности, 1941 страница.

Библиотека Страниц в секунду Пик памяти, МБ Сбои
Camelot stream 19.4 158 / 532 8 из 41
PyMuPDF find_tables() 11.0 157 / 227 0 из 41
pdfplumber 10.1 51 / 148 0 из 41
img2table 3.6 609 / 3967 2 из 41
Camelot lattice 3.5 294 / 460 8 из 41

Все 8 сбоев Camelot — файлы с запретом извлечения текста: их отклоняет pdfminer внутри Camelot.

Рендер и изображения

Рендер в 200 DPI на 100 сканах (2371 страница): pypdfium2 и pdfium-render — 4.9 страницы в секунду на ядро, PyMuPDF — 4.4, poppler — 3.7–3.9. На 16 процессах pdfium даёт 41 страницу в секунду при пике памяти 271 МБ, PyMuPDF — 37 при 1246 МБ.

Извлечение изображений сравнимо только при одинаковом результате. Требованию «JPEG и JPX как есть, CCITT, JBIG2 и Flate декодировать» отвечают mupdf-rs (61 страница в секунду), pdfium-render (52), PyMuPDF (24) и pypdfium2 (5).

Память на больших документах

На документах от 500 страниц (стандарт Unicode на 1140 страниц, скан с OCR-слоем, скан JBIG2/JPX) и на 1000 документах подряд в одном процессе утечек нет у mupdf-rs, PyMuPDF и pdfium. У extractous память растёт: 350 → 578 МБ.

Оговорки

  • Хост был нагружен (vLLM и около 45 контейнеров), поэтому разница меньше 10 % — в пределах шума.
  • Холодный старт — свежий процесс, файл выброшен из кеша страниц.
  • docling-parse исключён: около 6 страниц в секунду.
  • Сканы — с pravo.gov.ru (69), archive.org (24) и локальные (7).
  • Версии: PyMuPDF и mutool 1.28.2, pypdfium2 5.14 и pdfium-render 0.8.37 (pdfium chromium/8076), Poppler 25.03, pdfplumber 0.11.10, pypdf 6.21, mupdf-rs 0.5.