Недавно я работал над проектом 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`.
🐍!Удачного кодирования!🐍