Время прочтения: 4 мин.

Хочу представить нашим читателям, пару методов обработки исходных PDF-файлов, успешно внедренных мной.

  1. Иногда текст из файлов можно извлечь напрямую

На практике довольно часто встречаются PDF-файлы, которые были созданы конвертированием из doc/docx, из них можно извлечь текст напрямую с помощью библиотеки pdfminer.  

Для начала хорошо бы определить такие файлы из всей выборки (рис.1):

С помощью функции, реализованной выше мы извлекаем параметр Producer из метаинформации файла, если же конечно он присутствует. Он соответствует строчке «Приложение» при просмотре свойств pdf-файла (рис.2).

Отбираем те документы, которые были созданы с помощью Microsoft Word, извлеченный из них текст будет идеального качества.

Отмечу, что можно извлечь текст из документов, созданных с помощью программ ABBYY Finereader / PaperPort (такие документы уже содержат текст, распознанный с помощью встроенных в ПО алгоритмов). Однако этот текст уже был получен с помощью распознавания текста, а не конвертированием. И может быть ниже необходимой точности. Решать брать этот текст или самому «тюнить» Tesseract – решать вам.

С помощью этой функции из отобранных файлов можно постранично извлечь текст (рис.3):

Для тех же файлов, где извлечь текст нельзя – будем действовать так:

  • Преобразуем файл постранично в png;
  • Препроцессинг изображений (поворачиваем если нужно, убираем блики/засветы);
  • Определяем текст на изображении с помощью Tesseract.

2. Параллельные запуски

Ещё один способ ускорить обработку файлов – это параллельное выполнение. Моя реализация была осуществлена с помощью библиотеки concurrent.futures, а именно класса ProcessPoolExecutor – использующего многопроцессорность. Мы получаем пул процесса, отправляем туда задачи. Пул назначит задачи доступным ресурсам и запланирует их выполнение. ProcessPoolExecutor использует модуль multiprocessing и не подвержен блокировке GIL.

Распараллелить можно любую стадию из нашего пайплайна, я же рассмотрю только параллельную проверку на возможность извлечения текста из файла.

Делим весь список с путями к файлам на части по 64 элемента, чтобы не забивать пул задачами, то есть по сути устанавливаю этап синхронизации после каждых 64 элементов.

Каждому элементу из пачки файлов я применяю свою функцию обработки — get_data_prod. Пул назначит задачи доступным ресурсам и запланирует их выполнение. Параметр max_workers – это максимально допустимое число одновременно работающих процессов.

Модуль tqdm – нужен лишь как «обертка» над итератором для отрисовки прогресс бара в командной строке (рис.4).

Подобным образом можно распараллелить каждый этап из обработки PDF-файлов, и значительно ее ускорить. Но при этом следует иметь ввиду, что при параллельном запуске tesseract в разных процессах будут подняты сразу несколько экземпляров tesseract.exe, и доступной ОЗУ будет все меньше.

Общие советы о параллельности:

  • Не рекомендуется ставить число max_workers больше чем число физических ядер процессора
  • Также нужно следить за ОЗУ, так как при обработке огромных изображений 19200х22000 пикселей (встречался реальный случай) может возникнуть Exception. Он связан с тем, что при считывании изображения в оперативную память мы по сути создаем структуру numpy array, который реализован на C на основе массива. Если у нас одновременно запущена обработка нескольких таких больших изображений (max_workers), вполне вероятно, что мы не сможем выделить в ОЗУ непрерывный блок памяти соответствующего размера. В этом случае мы получим MemoryError. Эту проблему можно решить масштабированием подобных изображений.

О том, как извлечь информацию из PDF вы сможете в статье по ссылке