Кратко: В корпоративных архивах, юридических фирмах и финансовых организациях часто хранятся десятки тысяч PDF — от born-digital файлов с настоящим текстовым слоем до «псевдо-PDF» со сканеров 2005 года (полностраничные изображения, нельзя скопировать текст). Полный OCR на 100 000 файлов сжигает бюджет и повторно обрабатывает уже поисковые документы. Правильный путь: сначала пакетно определить, каким PDF действительно нужен OCR, затем маршрутизировать по типу в локальные или облачные движки распознавания.
Что значит «нужен OCR»
В инженерном контексте «нужен OCR» ≠ «в файле есть картинки». Это означает:
| Состояние | Признаки | Нужен OCR? |
|---|---|---|
| Born-digital | Встроенные шрифты, копируемый текст, pdftotext > 100 симв./стр. |
Нет |
| Поисковый, но плохой OCR | Текстовый слой есть, но с ошибками или пропусками | Частично |
| Чистый скан | JPEG/TIFF на всю страницу, без текстового слоя | Да |
| Гибрид | Обложка — изображение, в теле есть текст | Обычно нет |
Ключевая идея: Цель этапа проверки — не распознать содержание, а дёшево разложить 100k файлов по корзинам skip / partial / full-OCR до любого платного API или тяжёлого OCR.
Трёхуровневый пайплайн проверки
Одного прохода pdftotext недостаточно — ложные срабатывания и пропуски умножаются на объёме 100k. Используйте три уровня:
L1: Быстрая проверка текстового слоя (< 50 мс/файл)
PyMuPDF (fitz) или poppler pdftotext считают печатные символы:
avg_chars >= 80→SKIPavg_chars < 20→OCR_REQUIRED- Серая зона → L2
L2: Доля площади изображений на странице
Для серой зоны L1 вычисляйте площадь изображений / площадь страницы:
- Доля > 85% и мало символов L1 →
OCR_REQUIRED - Доля < 30% и умеренное число символов L1 →
SKIP - Иначе → L3 выборочная проверка
L3: Рендер выборки + лёгкий OCR-зонд
Для неопределённых файлов рендерьте только 1-ю, среднюю и последнюю страницы (всего 3). Запустите лёгкий macOS Vision или Tesseract. L3 обрабатывает лишь ~5–8% серой зоны.
Параллельная архитектура для 100 000 файлов
Горизонтальное масштабирование через манифест + очередь сообщений:
S3/MinIO bucket
└── manifest.jsonl (100k строк: path, sha256, size)
↓
Redis/RabbitMQ task queue
↓
N × Workers (Cloud Mac / Linux VM)
↓
SQLite / Parquet results
Пропускная способность (ZavCloud Cloud Mac mini M4, 24 ГБ):
| Этап | Скорость | Время на 100k |
|---|---|---|
| Только L1 | 12–18 файлов/сек | ~1,5–2,5 ч |
| L1 + L2 | 8–12 файлов/сек | ~2,5–3,5 ч |
| L1 + L2 + L3 выборка | 6–9 файлов/сек | ~3–5 ч |
Используйте ProcessPoolExecutor с 32 воркерами. Результаты пишите в Parquet для аналитики.
Трёхуровневая маршрутизация по вердиктам
| Verdict | Типичная доля | Действие |
|---|---|---|
SKIP |
55–70% | Прямая индексация |
PARTIAL |
10–20% | OCR только страниц с min_chars < 20 |
OCR_REQUIRED |
15–30% | Полный OCR → локальный Vision или облачный API |
Обязательно дедуплицируйте по SHA-256: дубликаты загрузок из разных систем — обычное дело. Кэш результатов на 90 дней экономит ещё 20–40% вычислений.
Выбор инструментов
| Инструмент | Скорость | Память | Лучше для |
|---|---|---|---|
| PyMuPDF | Очень быстро | Низкая | L1/L2 на 100k |
| pdftotext | Быстро | Низкая | Перекрёстная проверка L1 |
| pdfinfo | Очень быстро | Минимум | Метаданные: страницы, шифрование |
| Apache Tika | Средне | Высокая (JVM) | Смешанные Word/PPT/PDF |
| qpdf --check | Быстро | Низкая | Предфильтр повреждённых файлов |
Чистые PDF: PyMuPDF + pdftotext — оба должны вернуть SKIP, прежде чем пропускать файл.
Типичные ошибки
- Зашифрованные PDF: расшифруйте копию через
qpdf --decryptперед проверкой - Искажение CID-шрифтов: L1 завышает счётчик, но текст нечитаем → L3 проверяет долю печатного Unicode
- Двухслойные PDF (скан + скрытый OCR):
pdffonts— нет шрифтов, но текст есть → вероятно плохой существующий OCR →PARTIAL - Повреждённые файлы: исключения
fitz.open→ отдельная корзинаCORRUPT, не блокируйте основную очередь - Случайный I/O с NAS:
rsyncна локальный NVMe перед проверкой 100k мелких файлов
Зачем Cloud Mac для очередей проверки
Проверка PDF — это I/O + многопроцессный CPU, не GPU — но Cloud Mac подходит отлично:
- tmux 24/7: закрытие ноутбука убивает ночную очередь. Узлы Cloud Mac работают постоянно; проверка переходит в OCR-batch на той же машине.
- Unified Memory Apple Silicon: парсинг PyMuPDF выигрывает от пропускной способности памяти; L1 на M4 на 20–40% быстрее сопоставимых x86 VPS.
- Проверка → OCR на одном узле: файлы
OCR_REQUIREDидут в ocrmypdf + Vision без передачи 100k файлов между машинами. - Изоляция для compliance: юридические и финансовые клиенты часто требуют data residency — проверка и локальный OCR остаются на арендованном узле; облачный API обрабатывает только явно помеченные сложные страницы.
Чеклист из 7 шагов
- Экспортируйте
manifest.jsonlиз object storage (path + sha256 + size) - На Cloud Mac:
brew install poppler qpdf+pip install pymupdf pyarrow - Запустите полную проверку L1 → вывод в Parquet
- Вручную проверьте 200 файлов из корзины
PARTIAL, откалибруйте пороги OCR_REQUIRED→ очередь ocrmypdf;PARTIAL→ постраничный OCR- Запишите sidecar-файлы (
{sha256}.json) для RAG / ES индексации - Ежедневная инкрементальная проверка — не пересканируйте весь корпус
Итог: По меньшей мере половина затрат на OCR 100k PDF уходит на файлы, которым OCR никогда не был нужен. Сначала разложите корзины трёхуровневым пайплайном, затем выбирайте локальный Vision или облачный Document AI — так выглядит оцифровка документов в 2026 году.
ZavCloud Developer Infrastructure
Запустите проверку 100k PDF и OCR-очереди на Cloud Mac
Выделенный узел M4, tmux 24/7 batch, проверка и OCR на одной машине
Аренда на день для валидации пайплайна, затем неделя/месяц