Недавно я работал над проектом Python (конечно, для хакатона разработчиков), и мне нужна была библиотека для извлечения страниц из огромного PDF-документа в виде изображений. Основным вариантом использования было извлечение содержимого из документа PDF, и делать это блокирующим способом было дорого. Поэтому я искал варианты разделения страниц документа на несколько изображений, которые позволили бы мне одновременно извлекать содержимое.

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

Решение состоит в том, чтобы использовать пакет python `pdf2image` и написать всего 2 строки кода, чтобы извлечь страницы из документа PDF в виде изображений.

Настраивать

Несмотря на то, что решение довольно простое, вам необходимо установить утилиту под названием `poppler`, прежде чем вы начнете писать свой код на Python. Poppler — это базовая библиотека рендеринга PDF на основе C++, используемая pdf2image для рендеринга PDF-документа за кулисами.

MacOS

Настроить poppler на устройстве MacOS так же просто, как запустить `brew install poppler` (при условии, что на вашем компьютере установлен Homebrew).

Линукс

Если вы работаете на Linux-машине, что очень распространено, если вы запускаете приложение как контейнер, то процесс установки poppler может отличаться в зависимости от выбранного вами дистрибутива.

Если это машина/контейнер на основе Ubuntu, вы можете установить poppler с помощью apt-get -> sudo apt-get install poppler-utils

Windows

Процесс немного сложнее в Windows (как и все остальное в Windows 😋). Последние версии бинарника Windows можно найти здесь.

Извлеките zip-файл и добавьте `‹распакованную папку›/Library/bin` в переменную среды `PATH`.

Время для некоторого кода

После завершения настройки вы можете установить пакет `pdf2image` из pip и продолжить кодирование.

pip install pdf2image

Преобразовать из пути

Если PDF-файл, который вы хотите преобразовать, хорошо расположен в каталоге, то работа будет намного проще. Вы можете напрямую импортировать функцию `convert_from_path` из пакета pdf2image для извлечения страниц в виде изображений.

from pdf2image import convert_from_path
import os


# Checks if the output folder exists and if not it creates a new one
if not os.path.exists("extracted_images"):
 os.mkdir("extracted_images")

convert_from_path("top_secret_document.pdf", output_folder="extracted_images", fmt="jpeg")

Приведенный выше код выберет PDF-документ с именем `top_secret_document.pdf` из текущего пути и извлечет каждую отдельную страницу документа в виде изображения JPEG и сохранит его в выходной папке с именем `extracted_images. `.

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

Хорошая вещь в этой функции заключается в том, что она присваивает выходным изображениям UUID и добавляет счетчик страниц к имени файла, чтобы сделать имена файлов уникальными. Если вы хотите добавить общий префикс вместо использования UUID, вы можете использовать параметр `output_file`, принимаемый функцией.

Конвертировать из байтов

В проекте, над которым я работал, вариант использования выглядит следующим образом.

Пользователям предлагается загрузить документ, а загруженный файл отправляется в микросервис на основе Golang. Этот сервис делает некоторые проверки и другие вещи за кулисами. Как только вся обработка завершена, он сохраняет документ в корзину минио и публикует событие в теме кафки.

Служба python действует как потребитель, и как только событие получено, она извлекает PDF-документ из корзины и начинает процесс извлечения страницы. Это означает, что документ не будет легко доступен по пути файловой системы и будет доступен в виде потока байтов.

Это не эзотерическая тема для библиотеки `pdf2image`, и она легко поставляется с функцией `convert_from_bytes` для решения таких случаев использования.

# The get_object function fetches the PDF document stored in the object store
response = minio_client.get_object(bucket_name, "top_secret_document.pdf")

document_as_bytes = response.read()

images = convert_from_bytes(document_as_bytes, fmt="jpeg", output_folder="extracted_images")

Приведенный выше код будет читать документ PDF как байты и сохранять страницы в файлы изображений в выходном каталоге.

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

from pdf2image import convert_from_bytes

f = open('./top_secret_document.pdf', 'rb') #opening the file as a binary file

document_bytes = f.read()

images = convert_from_bytes(
 document_bytes, fmt="jpeg", output_folder="extracted_images")

При условии, что у нас уже есть функция convert_from_path для абстрагирования всего этого шаблона, я очень сомневаюсь, что кто-то когда-либо будет использовать функцию convert_from_bytes для работы с локальным файлом PDF, тем не менее я просто хотел показать, что это возможно

Заключение

Вот и все. Библиотека `pdf2image` не ограничивается легкими PDF-документами, она также может работать с объемными документами. Различные аргументы `convert_from_path` и `convert_from_bytes` можно использовать для управления процессом рендеринга PDF-документа и извлечения изображений различными способами.

Я прикрепил несколько полезных ссылок в справочном разделе ниже, которые можно использовать для более подробного изучения библиотеки `pdf2image`.

блокнот pdf2image

🐍!Удачного кодирования!🐍

Рекомендации

Официальные документы библиотеки

Попплер