Статья Извлечение текста, изображений и другие операции с документами PDF с помощью Python

PDF. Именно в этом формате мы читаем электронные книги, делаем презентации и руководства. И он действительно удобен тем, что дает возможность, вне зависимости от платформы, легко и просто работать с документами. Изначально, а может быть даже в первую очередь, данный формат был предназначен для представления в электронном виде полиграфической продукции. С июля 2008 года данный формат стал открытым. А на сегодняшний день, можно сказать, что он стал стандартом обмена электронными документами полиграфического качества уже подготовленными для печати. Но, несмотря на открытый стандарт, работать с контентом представленным в таком виде, на самом деле сложно. Давайте посмотрим, сможет ли Python хоть немного облегчить задачу по работе с форматом PDF.

000.jpg

Кроме создания документов в формате PDF над ним можно проводить разнообразные операции. Давайте рассмотрим сегодня несколько из них, а именно: сохранение текста из документа в файл; сохранение изображений; разделение документа на страницы; сборка одного документа из нескольких.


Что потребуется?

Для выполнения нужных нам операций потребуется две библиотеки. На самом деле, можно было бы обойтись одной, но в данном случае каждая из библиотек делает какую-то операцию чуть лучше, чем ее аналог. Давайте установим библиотеки pymupdf , PyPDF2 и img2pdf. Для этого пишем в терминале:

pip install pymupdf PyPDF2 img2pdf

После того, как библиотеки установились, нужно импортировать их в скрипт.

Python:
import os.path

import fitz
import img2pdf
from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger

Так же, нам понадобиться os.path, для корректного указания путей для сохранения и для проверки на наличие файлов и каталогов.


Извлечение текста из документа

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

Python:
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        return

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

Python:
    doc = fitz.open(path_doc)
    print(f'\n[+] Количество страниц документа: {doc.page_count}')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

Создадим список. В него мы будем добавлять полученный из документа текст постранично. Это нужно для того, чтобы не сохранять пустые документы. Дело в том, что не во всех PDF есть текстовый слой. К примеру, документ может быть собран из картинок. И, казалось бы, в этом случае считывать нечего и должно вызываться исключение. Но, этого не происходит, а сохраняется просто пустота. Потому, чтобы избежать лишнего создания пустых документов при отсутствии текстового слоя, будем делать проверку длины списка.

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

Python:
text_dict = []
    for current_page in range(len(doc)):
        print(f'\r[+] Считываю страницу: {current_page + 1}', end='')
        if doc.load_page(current_page).get_text("text") != "":
            text_dict.append(doc.load_page(current_page).get_text("text"))
    if len(text_dict) > 0:
        if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
            os.mkdir(os.path.join(os.getcwd(), doc_name))

        for text in text_dict:
            with open(os.path.join(os.getcwd(), doc_name, f"{doc_name}.txt"), 'a',
                      encoding='utf-8') as tex:
                tex.write(f'{text}\n')
…
print(f'\n[+] Сохранение текста pdf-документа "{doc_name}" завершено.')
    main()
    return

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

Python:
    else:
        print('\n[+] Документ не имеет текстового слоя')
        main()
        return

Python:
def text_extract(path_doc):
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        return

    doc = fitz.open(path_doc)
    print(f'\n[+] Количество страниц документа: {doc.page_count}')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

    text_dict = []
    for current_page in range(len(doc)):
        print(f'\r[+] Считываю страницу: {current_page + 1}', end='')
        if doc.load_page(current_page).get_text("text") != "":
            text_dict.append(doc.load_page(current_page).get_text("text"))
    if len(text_dict) > 0:
        if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
            os.mkdir(os.path.join(os.getcwd(), doc_name))

        for text in text_dict:
            with open(os.path.join(os.getcwd(), doc_name, f"{doc_name}.txt"), 'a',
                      encoding='utf-8') as tex:
                tex.write(f'{text}\n')
    else:
        print('\n[+] Документ не имеет текстового слоя')
        main()
        return
    print(f'\n[+] Сохранение текста pdf-документа "{doc_name}" завершено.')
    main()
    return


Извлечение картинок из PDF-документа

Следующая функция, которую мы создадим, это функция извлечения картинок из документа. Иногда это бывает очень полезно. Но, в некоторых документах присутствует некоторая каша из разнообразных заголовков, кусков больших картинок, а потому, при извлечении получается большая куча всякой всячины. Но, тем не менее, если в документе полноценные картинки, их извлечение может быть полезным. Создадим функцию image_extract(path_doc). На входе она также будет принимать путь к документу.

Первым делом проверим, есть ли документ, который передал пользователь и является ли документ pdf. Проверка аналогична той, что мы проводили в предыдущей функции. Изначально я хотел сделать одну функцию для проверки на наличие файла и его расширение, но после понял, что количество кода от этого не особо уменьшиться. Так как вместе с проверкой нужно было бы передавать пользовательский выбор, а, следовательно, после проверки на наличие файла, делать еще и проверку на выбор пользователя, чтобы запустить соответствующую функцию. Потому, от этой идеи я отказался.

Python:
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        main()
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        main()
        return

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

Python:
    doc = fitz.open(path_doc)
    print(f'\n[+] Количество страниц документа: {doc.page_count}')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

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

Python:
    if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
        os.mkdir(os.path.join(os.getcwd(), doc_name))
    if not os.path.exists(os.path.join(os.getcwd(), doc_name, 'images')):
        os.mkdir(os.path.join(os.getcwd(), doc_name, 'images'))

Устанавливаем счетчик. Он нужен будет для двух целей. Первая, это вывод информации о сохраненных картинках, то есть их количестве, для пользователя. А вторая, и основная, это сохранение файлов с картинками под разными номерами. Теперь создаем цикл с количеством страниц документа. Он будет нужен для того, чтобы открыть каждую страницу по отдельности. В нем запустим дополнительный цикл, в котором с помощью функции doc.get_page_images(i) будем получать все картинки с определенной страницы. Затем получаем номер ссылки на изображение и создаем пиксельную карту с помощью Pixmap. Затем данную пиксельную карту преобразовываем из CMYK в пиксельную карту RGB.

Python:
page_count = 0
    for i in range(len(doc)):
        for img in doc.get_page_images(i):
            xref = img[0]
            pix = fitz.Pixmap(doc, xref)
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            page_count += 1
            pix1.save(os.path.join(os.getcwd(), doc_name, 'images', f'image_0{page_count}.png'))
            print(f'\r[+] Изображение {page_count} сохранено', end='')
    print(f'\n[+] Сохранение изображений pdf-документа "{doc_name}" завершено.')
    main()
    return

Увеличиваем счетчик на единицу и сохраняем изображение, о чем после сообщаем пользователю с помощью принта. Ну и после завершения всех циклов выводим принт об успешном сохранении всех изображений.

Python:
def image_extract(path_doc):
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        main()
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        main()
        return

    doc = fitz.open(path_doc)
    print(f'\n[+] Количество страниц документа: {doc.page_count}')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

    if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
        os.mkdir(os.path.join(os.getcwd(), doc_name))
    if not os.path.exists(os.path.join(os.getcwd(), doc_name, 'images')):
        os.mkdir(os.path.join(os.getcwd(), doc_name, 'images'))

    page_count = 0
    for i in range(len(doc)):
        for img in doc.get_page_images(i):
            xref = img[0]
            pix = fitz.Pixmap(doc, xref)
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            page_count += 1
            pix1.save(os.path.join(os.getcwd(), doc_name, 'images', f'image_0{page_count}.png'))
            print(f'\r[+] Изображение {page_count} сохранено', end='')
    print(f'\n[+] Сохранение изображений pdf-документа "{doc_name}" завершено.')
    main()
    return


Разбивка PDF-файлов на страницы

Для разбивки документа на страницы создадим функцию pages_split(path_doc), которая на входе принимает путь к файлу. Делаем все те же проверки на наличие файла и его расширение:

Python:
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        main()
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        main()
        return

Будем использовать библиотеку PyPDF2. Создаем объект PdfFileReader, в который считываем содержимое документа. Выводим на печать количество страниц для информации пользователю. Получаем имя документа из пути к нему.

Python:
    pdf = PdfFileReader(path_doc)
    print(f'\n[+] Количество страниц документа: {pdf.getNumPages()}\n')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

Затем создаем необходимые папки для сохранения документа постранично.

Python:
    if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
        os.mkdir(os.path.join(os.getcwd(), doc_name))
    if not os.path.exists(os.path.join(os.getcwd(), doc_name, 'pages')):
        os.mkdir(os.path.join(os.getcwd(), doc_name, 'pages'))

В цикле пробегаемся по диапазону с количеством страниц документа. Создаем объект PdfFileWriter() для записи страницы. Открываем страницу и добавляем ее в объект для записи, после чего сохраняем страницу в файл и выводим сообщение об успешном сохранении и так до конца документа.

Python:
    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        current_page = pdf.getPage(page)
        pdf_writer.addPage(current_page)
        with open(os.path.join(os.getcwd(), doc_name, 'pages', f'{doc_name}_{page + 1}.pdf'), "wb") as out:
            pdf_writer.write(out)
        print(f'\r[+] Страница {page + 1} сохранена', end='')

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

Python:
def pages_split(path_doc):
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        main()
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        main()
        return

    pdf = PdfFileReader(path_doc)
    print(f'\n[+] Количество страниц документа: {pdf.getNumPages()}\n')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

    if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
        os.mkdir(os.path.join(os.getcwd(), doc_name))
    if not os.path.exists(os.path.join(os.getcwd(), doc_name, 'pages')):
        os.mkdir(os.path.join(os.getcwd(), doc_name, 'pages'))

    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        current_page = pdf.getPage(page)
        pdf_writer.addPage(current_page)
        with open(os.path.join(os.getcwd(), doc_name, 'pages', f'{doc_name}_{page + 1}.pdf'), "wb") as out:
            pdf_writer.write(out)
        print(f'\r[+] Страница {page + 1} сохранена', end='')
    print(f'\n[+] Сохранение страниц pdf-документа "{doc_name}" завершено.')
    main()
    return


Объединение отдельных страниц или PDF-документов в один

Следующая функция, это функция объединения документов. Назовем ее pages_merge(path_doc, name_file). На вход она получает путь к папке с документами, а также название объединенного документа.

Делаем проверки. Если в предыдущих функциях мы делали проверки на наличие файла и его расширение, то здесь мы делаем проверку уже на наличие папки. Если папка существует, делаем проверку на количество файлов в папке. Если она пустая или количество файлов в ней меньше или равно 1, то сообщаем об этом пользователю, так как, если файл один, следовательно, и объединять нечего, не говоря уже о полном отсутствии файлов. И выходим из функции в пользовательский выбор.

Python:
    if not os.path.isdir(path_doc):
        print('[+] Папка не найдена')
        main()
        return
    if len(os.listdir(path_doc)) <= 1:
        print('[+] В папке нет файлов для объединения')
        main()
        return

Затем создаем объект PdfFileMerger(). Устанавливаем счетчик, который в принципе не обязателен, но, чтобы пользователю не было скучно, будем выводить в терминал принты о каждом добавленном файле. Дальше пробегаемся по списку полученных файлов в цикле. Проверяем, является ли объект в списке файлом, если да, имеет ли он расширение pdf. И если да, то печатаем принт пользователю, считываем содержимое файла побайтово, после чего добавляем в объект PdfFileMerger. И увеличиваем счетчик на единицу.

Python:
    for file in os.listdir(path_doc):
        if os.path.isfile(os.path.join(path_doc, file)):
            if file.endswith('.pdf'):
                print(f'\r[+] Объединяю файлы: {count} подождите...', end='')
                with open(os.path.join(path_doc, file), 'rb') as pdf_file:
                    source_file = PdfFileReader(pdf_file)
                    merger.append(source_file)
                count += 1

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

Python:
merger.write(f'{name_file}.pdf')
    print(f'\n[+] Объединение страниц в pdf-документ "{name_file}.pdf" завершено.')
    main()
    return

Python:
def pages_merge(path_doc, name_file):
    if not os.path.isdir(path_doc):
        print('[+] Папка не найдена')
        main()
        return
    if len(os.listdir(path_doc)) <= 1:
        print('[+] В папке нет файлов для объединения')
        main()
        return

    merger = PdfFileMerger()

    count = 1
    for file in os.listdir(path_doc):
        if os.path.isfile(os.path.join(path_doc, file)):
            if file.endswith('.pdf'):
                print(f'\r[+] Объединяю файлы: {count} подождите...', end='')
                with open(os.path.join(path_doc, file), 'rb') as pdf_file:
                    source_file = PdfFileReader(pdf_file)
                    merger.append(source_file)
                count += 1
    merger.write(f'{name_file}.pdf')
    print(f'\n[+] Объединение страниц в pdf-документ "{name_file}.pdf" завершено.')
    main()
    return


Объединение изображений в PDF-документ

Следующая функция, это функция объединения изображений распространенных форматов (jpg, jpeg, gif, png, tiff). С ее помощью из изображений можно собрать документ буквально в несколько секунд. Создадим функцию merge_images(path_doc, title). На входе она принимает путь к папке с изображениями и название выходного документа pdf.

Затем проверяем, существует ли папка переданная пользователем. Так как изображений должно быть хотя бы одно, сканируем директорию на наличие в ней файлов. Проверяем, не является ли она пустой. Создаем счетчик, чтобы показать пользователю, что что-то обрабатывается, затем в цикле перебираем содержимое переданной пользователем директории, проверяем, является ли файл в списке файлом, затем проверяем его расширение, чтобы не добавлять в список документы word или excel. Ну и если все звезды сходятся в одном месте, добавляем изображение в список.

Python:
def merge_images(path_doc, title):
    if not os.path.isdir(path_doc):
        print('\n[+] Указанной папки не существует. Проверьте введенные данные')
        main()
        return

    if len(os.listdir(path_doc)) > 0:
        image_list = []
        count = 1
        for image in os.listdir(path_doc):
            if os.path.isfile(os.path.join(path_doc, image)):
                if image.split(".")[-1] in ['jpg', 'jpeg', 'bmp', 'png', 'tiff', 'gif']:
                    image_list.append(os.path.join(path_doc, image))
                    print(f'\r[+] Дабавлено {count}-е изображение', end='')
                    count += 1

        if len(image_list) > 0:
            print('\n[+] Обработка добавленных изображений...')
            with open(f'{title}.pdf', 'wb') as file:
                file.write(img2pdf.convert(image_list))
            print(f'\n[+] Объединение изображений в pdf-документ "{title}.pdf" завершено.')
            main()
            return
        else:
            print('\n[+] В папке нет файлов изображений. Проверьте правильность пути к изображениям')
            main()
            return

После того, как завершиться цикл, а значит, будут обработаны все файлы, проверяем, не является ли список файлов пустым. Так как в папке может не оказаться изображений, а следовательно в список ничего не добавиться и обрабатывать будет нечего. Затем, если список не нулевой, передаем его в функцию конвертации изображений в pdf, и сохраняем побайтово в файл с переданным пользователем именем. После завершения операции возвращаемся в функцию пользовательского выбора. Если же список является нулевым сообщаем, что в папке, которую он передал, нет изображений и выходим из функции в пользовательский выбор.

Здесь надо упомянуть то, что файлы должны называться правильно, если вы хотите объединить их в нужном порядке. То есть, желательно, пронумерованы. Нумерация должна начинаться не с 1, к примеру: image_1.png, а с 01, то есть: image_01.png. Иначе файл, который у вас должен быть в документе первым, будет идти где-то за 19-й страницей.


Функция пользовательского выбора

Ну и еще одна функция, это функция main(). В ней мы запрашиваем у пользователя нужное действие. Затем делаем проверку, какую цифру он ввел. И в соответствии с этим запускаем нужную функцию, передавая в нее путь к файлу, который тут же и запрашиваем у пользователя. Если же что-то пошло не так и пользователь ввел не то, что нужно, возвращаем его к самому началу.

Python:
def main():
    user_input = input('\n[+] Выберите действие:\n   [1] Сохранить текст из PDF\n   [2] Сохранить картинки из PDF\n'
                       '   [3] Разделить документ PDF на страницы\n   [4] Объединить PDF-документ из страниц\n   '
                       '[5] Объединить картинки в PDF\n   [6] Выход\n   >>> ')

    if user_input == "1":
        text_extract(input('\n[+] Введите путь к файлу pdf >>> '))
    elif user_input == "2":
        image_extract(input('\n[+] Введите путь к файлу pdf >>> '))
    elif user_input == "3":
        pages_split(input('\n[+] Введите путь к файлу pdf >>> '))
    elif user_input == "4":
        pages_merge(input('\n[+] Введите путь к папке с файлами >>> '),
                    input('[+] Введите имя создаваемого pdf >>> '))
    elif user_input == "5":
        merge_images(input('\n[+] Введите путь к папке с картинками >>> '),
                     input('[+] Введите имя создаваемого pdf >>> '))
    elif user_input == "6":
        exit(0)
    else:
        print('\n[+] Неопознанный выбор. Попробуйте снова')
        main()
        return

На этом создание скрипта можно закончить. С помощью библиотек pymupdf и PyPDF2 работа с документами в pdf-формате становиться в принципе возможной. Конечно же, при извлечении текста из документов порою попадаются странные символы, но с этим в данном случае ничего особо не поделаешь. Так как с помощью данных библиотек только лишь извлекается текстовый слой, а не распознается полученный текст. Ну и, конечно же, структура полученного текстового документа оставляет желать лучшего. Конечно, она почти такая же, как и в оригинале, но за счет того, что в оригинале идет перенос на другую строку, предложения получаются несвязные. И если в тексте, который вы не будете дальше обрабатывать, а просто читать, это еще более-менее допустимо, то вот уже в, например, тексте на английском языке, если вы его будете переводить, строки придется объединять, так как иначе переводчик будет переводить построчно, а не по предложениям, из-за чего будет искажаться смысл.

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

Python:
# pip install pymupdf
# pip install PyPDF2
# pip install img2pdf

import os.path

import fitz
import img2pdf
from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger


# извлечение текста из PDF документа
def text_extract(path_doc):
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        return

    doc = fitz.open(path_doc)
    print(f'\n[+] Количество страниц документа: {doc.page_count}')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

    text_dict = []
    for current_page in range(len(doc)):
        print(f'\r[+] Считываю страницу: {current_page + 1}', end='')
        if doc.load_page(current_page).get_text("text") != "":
            text_dict.append(doc.load_page(current_page).get_text("text"))
    if len(text_dict) > 0:
        if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
            os.mkdir(os.path.join(os.getcwd(), doc_name))

        for text in text_dict:
            with open(os.path.join(os.getcwd(), doc_name, f"{doc_name}.txt"), 'a',
                      encoding='utf-8') as tex:
                tex.write(f'{text}\n')
    else:
        print('\n[+] Документ не имеет текстового слоя')
        main()
        return
    print(f'\n[+] Сохранение текста pdf-документа "{doc_name}" завершено.')
    main()
    return


# извлечение изображений из PDF документа
def image_extract(path_doc):
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        main()
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        main()
        return

    doc = fitz.open(path_doc)
    print(f'\n[+] Количество страниц документа: {doc.page_count}')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

    if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
        os.mkdir(os.path.join(os.getcwd(), doc_name))
    if not os.path.exists(os.path.join(os.getcwd(), doc_name, 'images')):
        os.mkdir(os.path.join(os.getcwd(), doc_name, 'images'))

    page_count = 0
    for i in range(len(doc)):
        for img in doc.get_page_images(i):
            xref = img[0]
            pix = fitz.Pixmap(doc, xref)
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            page_count += 1
            pix1.save(os.path.join(os.getcwd(), doc_name, 'images', f'image_0{page_count}.png'))
            print(f'\r[+] Изображение {page_count} сохранено', end='')
    print(f'\n[+] Сохранение изображений pdf-документа "{doc_name}" завершено.')
    main()
    return


# разбивка PDF-файлов на страницы
def pages_split(path_doc):
    if not os.path.isfile(path_doc):
        print('[+] Файл не найден')
        main()
        return
    if not path_doc.endswith('.pdf'):
        print('[+] Неверное расширение файла')
        main()
        return

    pdf = PdfFileReader(path_doc)
    print(f'\n[+] Количество страниц документа: {pdf.getNumPages()}\n')

    doc_name = os.path.split(path_doc)[-1].removesuffix('.pdf')

    if not os.path.exists(os.path.join(os.getcwd(), doc_name)):
        os.mkdir(os.path.join(os.getcwd(), doc_name))
    if not os.path.exists(os.path.join(os.getcwd(), doc_name, 'pages')):
        os.mkdir(os.path.join(os.getcwd(), doc_name, 'pages'))

    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        current_page = pdf.getPage(page)
        pdf_writer.addPage(current_page)
        with open(os.path.join(os.getcwd(), doc_name, 'pages', f'{doc_name}_{page + 1}.pdf'), "wb") as out:
            pdf_writer.write(out)
        print(f'\r[+] Страница {page + 1} сохранена', end='')
    print(f'\n[+] Сохранение страниц pdf-документа "{doc_name}" завершено.')
    main()
    return


# объединение документов PDF в один
def pages_merge(path_doc, name_file):
    if not os.path.isdir(path_doc):
        print('[+] Папка не найдена')
        main()
        return
    if len(os.listdir(path_doc)) <= 1:
        print('[+] В папке нет файлов для объединения')
        main()
        return

    merger = PdfFileMerger()

    count = 1
    for file in os.listdir(path_doc):
        if os.path.isfile(os.path.join(path_doc, file)):
            if file.endswith('.pdf'):
                print(f'\r[+] Объединяю файлы: {count} подождите...', end='')
                with open(os.path.join(path_doc, file), 'rb') as pdf_file:
                    source_file = PdfFileReader(pdf_file)
                    merger.append(source_file)
                count += 1
    merger.write(f'{name_file}.pdf')
    print(f'\n[+] Объединение страниц в pdf-документ "{name_file}.pdf" завершено.')
    main()
    return


# объединение картинок в pdf-документ
def merge_images(path_doc, title):
    if not os.path.isdir(path_doc):
        print('\n[+] Указанной папки не существует. Проверьте введенные данные')
        main()
        return

    if len(os.listdir(path_doc)) > 0:
        image_list = []
        count = 1
        for image in os.listdir(path_doc):
            if os.path.isfile(os.path.join(path_doc, image)):
                if image.split(".")[-1] in ['jpg', 'jpeg', 'bmp', 'png', 'tiff', 'gif']:
                    image_list.append(os.path.join(path_doc, image))
                    print(f'\r[+] Дабавлено {count}-е изображение', end='')
                    count += 1

        if len(image_list) > 0:
            print('\n[+] Обработка добавленных изображений...')
            with open(f'{title}.pdf', 'wb') as file:
                file.write(img2pdf.convert(image_list))
            print(f'\n[+] Объединение изображений в pdf-документ "{title}.pdf" завершено.')
            main()
            return
        else:
            print('\n[+] В папке нет файлов изображений. Проверьте правильность пути к изображениям')
            main()
            return


# выбор пользователем нужных действий
def main():
    user_input = input('\n[+] Выберите действие:\n   [1] Сохранить текст из PDF\n   [2] Сохранить картинки из PDF\n'
                       '   [3] Разделить документ PDF на страницы\n   [4] Объединить PDF-документ из страниц\n   '
                       '[5] Объединить картинки в PDF\n   [6] Выход\n   >>> ')

    if user_input == "1":
        text_extract(input('\n[+] Введите путь к файлу pdf >>> '))
    elif user_input == "2":
        image_extract(input('\n[+] Введите путь к файлу pdf >>> '))
    elif user_input == "3":
        pages_split(input('\n[+] Введите путь к файлу pdf >>> '))
    elif user_input == "4":
        pages_merge(input('\n[+] Введите путь к папке с файлами >>> '),
                    input('[+] Введите имя создаваемого pdf >>> '))
    elif user_input == "5":
        merge_images(input('\n[+] Введите путь к папке с картинками >>> '),
                     input('[+] Введите имя создаваемого pdf >>> '))
    elif user_input == "6":
        exit(0)
    else:
        print('\n[+] Неопознанный выбор. Попробуйте снова')
        main()
        return


if __name__ == "__main__":
    main()

А на этом, пожалуй, все.

Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
 
Последнее редактирование:
  • Нравится
Реакции: And4R и Notsaint
Мы в соцсетях: