Как работать с PDF в Python

1 июня, 2020

Подписывайся на наш канал в Telegram, чтобы ежедневно совершенствоваться в Python - перейти

Оглавление

  • История pyPdf, PyPDF2 и PyPDF4
  • pdfrw: альтернатива
  • Установка
  • Как извлечь информацию о документе из PDF в Python
  • Как вращать страницы
  • Как объединить PDF-файлы
  • Как разделить PDF-файлы
  • Как добавить водяные знаки
  • Как зашифровать PDF
  • Вывод
  • Дальнейшее чтение

Формат переносимого документа, или PDF, – это формат файла, который можно использовать для надежного представления и обмена документами в операционных системах. Хотя PDF изначально был изобретен Adobe, сейчас это открытый стандарт, который поддерживается Международной организацией по стандартизации (ISO). Вы можете работать с уже существующим PDF в Python, используя пакет PyPDF2.

PyPDF2 представляет собой пакет на чистом Python, который вы можете использовать для различных типов операций PDF.

К концу этой статьи вы будете знать, как сделать следующее:

  • Извлечение информации о документе из PDF в Python
  • Поворот страниц
  • Объединение PDF-файлов
  • Разделение PDF-файлов
  • Добавление водяных знаков
  • Шифрование PDF

Давайте начнем!

История pyPdfPyPDF2 и PyPDF4

Оригинальный pyPdf пакет был выпущен еще в 2005 году, последний официальный релиз pyPdf был в 2010 году. По прошествии около года, компания под названием Phasit спонсировал pyPdf и теперь он называется PyPDF2. Код был написан для обратной совместимости с оригиналом и работал довольно хорошо в течение нескольких лет, последний выпуск был в 2016 году.

Была краткая серия выпусков пакета под названием PyPDF3, а затем проект переименован в PyPDF4. Все эти проекты делают одно и то же, но самое большое отличие между pyPdf и PyPDF2 +, заключается в том, что в последних версиях добавлена ​​поддержка Python 3. Существует другая ветка pyPdf для Python 3 , но она не поддерживалась в течение многих лет.

В то время как PyPDF2 был заброшен, новый PyPDF4 не имеет полной обратной совместимости с PyPDF2. Большинство примеров в этой статье будут прекрасно работать PyPDF4, но есть и такие, которые не могут, поэтому PyPDF4 в этой статье не рассматриваются более подробно. Можете поменять импорт PyPDF2 на PyPDF4, и посмотреть , как это работает для вас.

pdfrw: Альтернатива

Патрик Маупин создал пакет под названием pdfrw, который может делать то же самое, что и PyPDF2. Вы можете использовать pdfrw для всех тех же видов задач, которые вы узнаете, как выполнять в этой статье используя PyPDF2, с заметным исключением шифрования.

Самое большое различие pdfrw в том, что он интегрируется с пакетом ReportLab , так что вы можете взять уже существующий PDF-файл и создать новый с помощью ReportLab, используя некоторые или все существующие PDF-файлы.

Установка

Установка PyPDF2 может быть сделана используя pip или conda если вам придется пользоваться Anaconda вместо обычного Python.

Вот как вы должны установить PyPDF2 с pip:

$ pip install pypdf2

Установка довольно быстрая, так как PyPDF2 не имеет никаких зависимостей.

Теперь давайте продолжим и узнаем, как извлечь некоторую информацию из PDF.

Как извлечь информацию о документе из PDF в Python

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

Вот текущие типы данных, которые могут быть извлечены:

  • Автор
  • Творец
  • Режиссер
  • Тема
  • Заглавие
  • Количество страниц

Вам нужно найти PDF для использования в этом примере. Вы можете использовать любой PDF-файл, который у вас есть на вашем компьютере. Чтобы упростить задачу, я пошел в Leanpub и взял образец одной из моих книг для этого упражнения. Образец, который вы хотите загрузить, называется reportlab-sample.pdf.

Давайте напишем некоторый код с использованием этого PDF и узнаем, как вы можете получить доступ к этим атрибутам:

# extract_doc_info.py

from PyPDF2 import PdfFileReader

def extract_information(pdf_path):
    with open(pdf_path, 'rb') as f:
        pdf = PdfFileReader(f)
        information = pdf.getDocumentInfo()
        number_of_pages = pdf.getNumPages()

    txt = f"""
    Information about {pdf_path}: 

    Author: {information.author}
    Creator: {information.creator}
    Producer: {information.producer}
    Subject: {information.subject}
    Title: {information.title}
    Number of pages: {number_of_pages}
    """

    print(txt)
    return information

if __name__ == '__main__':
    path = 'reportlab-sample.pdf'
    extract_information(path)

Здесь вы импортируете PdfFileReader из пакета PyPDF2. Это класс PdfFileReader с несколькими методами взаимодействия с файлами PDF. В этом примере вы вызываете .getDocumentInfo(), который вернет экземпляр DocumentInformation. Он содержит большую часть интересующей вас информации. Вы также вызываете .getNumPages() объект reader, который возвращает количество страниц в документе.

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

Хотя PyPDF2 имеет .extractText(), который можно использовать на объектах своей страницы (не показано в этом примере), он работает не очень хорошо. Некоторые PDF-файлы будут возвращать текст, а некоторые – пустую строку. PDFMiner гораздо более надежный и был специально разработан для извлечения текста из PDF-файлов.

Теперь вы готовы узнать о вращении страниц PDF.

Как вращать страницы

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

В этом примере вы можете выбрать реальную статью на Python и распечатать ее в формате PDF.

Давайте узнаем, как вращать несколько страниц этой статьи с помощью PyPDF2:

# rotate_pages.py

from PyPDF2 import PdfFileReader, PdfFileWriter

def rotate_pages(pdf_path):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(pdf_path)
    # Rotate page 90 degrees to the right
    page_1 = pdf_reader.getPage(0).rotateClockwise(90)
    pdf_writer.addPage(page_1)
    # Rotate page 90 degrees to the left
    page_2 = pdf_reader.getPage(1).rotateCounterClockwise(90)
    pdf_writer.addPage(page_2)
    # Add a page in normal orientation
    pdf_writer.addPage(pdf_reader.getPage(2))

    with open('rotate_pages.pdf', 'wb') as fh:
        pdf_writer.write(fh)

if __name__ == '__main__':
    path = 'Jupyter_Notebook_An_Introduction.pdf'
    rotate_pages(path)

Для этого примера вам нужно импортировать PdfFileWriter в дополнение к PdfFileReader, потому что вам нужно будет выписать новый PDF.  rotate_pages()берет путь к PDF, который вы хотите изменить. Внутри этой функции вам нужно будет создать объект записи, который вы можете назвать pdf_writer, и объект чтения, называемый pdf_reader.

Далее вы можете использовать, .GetPage() чтобы получить нужную страницу. Здесь вы берете нулевую страницу, которая является первой страницей. Затем вы вызываете метод объекта страницы .rotateClockwise() и переходите на 90 градусов. Затем для второй страницы вы также вызываете .rotateCounterClockwise()и проходите ее на 90 градусов.

Примечание . Пакет PyPDF2 позволяет поворачивать страницу только с шагом 90 градусов. Иначе вы получите AssertionError.

После каждого вызова методов ротации вы вызываете .addPage(). Это добавит повернутую версию страницы к объекту записи. Последняя страница, которую вы добавляете к объекту записи – это страница 3 без поворота.

Наконец вы пишете новый PDF с помощью .write(). В качестве параметра он принимает файлоподобный объект . Этот новый PDF будет содержать три страницы. Первые два будут вращаться в противоположных направлениях друг от друга и будут в альбомной ориентации, в то время как третья страница является обычной страницей.

Теперь давайте узнаем, как вы можете объединить несколько PDF-файлов в один.

Как объединить PDF-файлы

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

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

Давайте продолжим и напишем некоторый код, который вы можете использовать для объединения PDF-файлов:

# pdf_merging.py

from PyPDF2 import PdfFileReader, PdfFileWriter

def merge_pdfs(paths, output):
    pdf_writer = PdfFileWriter()

    for path in paths:
        pdf_reader = PdfFileReader(path)
        for page in range(pdf_reader.getNumPages()):
            # Add each page to the writer object
            pdf_writer.addPage(pdf_reader.getPage(page))

    # Write out the merged PDF
    with open(output, 'wb') as out:
        pdf_writer.write(out)

if __name__ == '__main__':
    paths = ['document1.pdf', 'document2.pdf']
    merge_pdfs(paths, output='merged.pdf')

Вы можете использовать merge_pdfs(), когда у вас есть список PDF-файлов, которые вы хотите объединить вместе. Вам также необходимо знать, где сохранить результат, поэтому эта функция принимает список входных путей и выходной путь.

Затем вы перебираете входные данные и создаете объект для чтения PDF, для каждого из них. Далее вы будете перебирать все страницы в файле PDF и использовать .addPage(), для добавления каждой из этих страниц к себе.

Как только вы закончите итерацию по всем страницам всех PDF-файлов в вашем списке, вы выведете результат в конце.

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

Давайте узнаем, как сделать обратное слияние!

Как разделить PDF-файлы

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

Вот как вы можете использовать PyPDF2 для разделения вашего PDF на несколько файлов:

# pdf_splitting.py

from PyPDF2 import PdfFileReader, PdfFileWriter

def split(path, name_of_split):
    pdf = PdfFileReader(path)
    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        pdf_writer.addPage(pdf.getPage(page))

        output = f'{name_of_split}{page}.pdf'
        with open(output, 'wb') as output_pdf:
            pdf_writer.write(output_pdf)

if __name__ == '__main__':
    path = 'Jupyter_Notebook_An_Introduction.pdf'
    split(path, 'jupyter_page')

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

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

Как добавить водяные знаки

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

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

Давайте узнаем, как добавить водяной знак сейчас:

# pdf_watermarker.py

from PyPDF2 import PdfFileWriter, PdfFileReader

def create_watermark(input_pdf, output, watermark):
    watermark_obj = PdfFileReader(watermark)
    watermark_page = watermark_obj.getPage(0)

    pdf_reader = PdfFileReader(input_pdf)
    pdf_writer = PdfFileWriter()

    # Watermark all the pages
    for page in range(pdf_reader.getNumPages()):
        page = pdf_reader.getPage(page)
        page.mergePage(watermark_page)
        pdf_writer.addPage(page)

    with open(output, 'wb') as out:
        pdf_writer.write(out)

if __name__ == '__main__':
    create_watermark(
        input_pdf='Jupyter_Notebook_An_Introduction.pdf', 
        output='watermarked_notebook.pdf',
        watermark='watermark.pdf')

create_watermark() принимает три аргумента:

  1. input_pdf: путь к файлу PDF с водяным знаком
  2. output:  путь, по которому вы хотите сохранить версию PDF с водяным знаком
  3. watermark: PDF-файл, содержащий изображение или текст водяного знака

В коде вы открываете водяной знак PDF и берете только первую страницу документа, поскольку именно там должен находиться ваш водяной знак. Затем вы создаете объект для чтения PDF, используя общий объект input_pdf и pdf_writer для записи PDF с водяными знаками.

Следующим шагом будет перебирать страницы в input_pdf. Здесь происходит волшебство. Вам нужно будет вызвать .mergePage() и передать его watermark_page. Когда вы это сделаете, он будет перекрывать верхнюю часть watermark_pageтекущей страницы. Затем вы добавляете эту недавно слитую страницу в ваш  объект pdf_writer.

Наконец, вы записываете новый PDF-файл с водяными знаками на диск, и все готово!

Последняя тема, о которой вы узнаете – как работает PyPDF2 шифрование.

Как зашифровать PDF

В настоящее время в PyPDF2 поддерживается только добавление пароля пользователя и пароля владельца в существующий PDF. В PDF land пароль владельца в основном дает вам права администратора по сравнению с PDF и позволяет вам устанавливать права доступа к документу. С другой стороны, пароль пользователя позволяет вам открыть документ.

Насколько я могу судить, PyPDF2 самом деле не позволяет вам устанавливать какие-либо разрешения для документа, хотя это позволяет вам установить пароль владельца.

Независимо от того, как вы можете добавить пароль, который также зашифрует PDF:

# pdf_encrypt.py

from PyPDF2 import PdfFileWriter, PdfFileReader

def add_encryption(input_pdf, output_pdf, password):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(input_pdf)

    for page in range(pdf_reader.getNumPages()):
        pdf_writer.addPage(pdf_reader.getPage(page))

    pdf_writer.encrypt(user_pwd=password, owner_pwd=None, 
                       use_128bit=True)

    with open(output_pdf, 'wb') as fh:
        pdf_writer.write(fh)

if __name__ == '__main__':
    add_encryption(input_pdf='reportlab-sample.pdf',
                   output_pdf='reportlab-encrypted.pdf',
                   password='twofish')

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

Последний шаг – вызов .encrypt(), который берет пароль пользователя, пароль владельца и нужно ли добавлять 128-битное шифрование. По умолчанию включено 128-битное шифрование. Если вы установите его False, то вместо этого будет применено 40-битное шифрование.

Примечание: для шифрования PDF используется либо RC4, либо AES (расширенный стандарт шифрования) для шифрования PDF в соответствии с pdflib.com.

Тот факт, что вы зашифровали свой PDF, не означает, что он безопасен. Есть инструменты для удаления паролей из PDF-файлов. Если вы хотите узнать больше, у университета Карнеги-Меллона есть интересная статья на эту тему .

Вывод

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

В этом уроке вы узнали, как сделать следующее:

  • Извлечение метаданных из PDF
  • Поворот страниц
  • Слияние и разделение PDF-файлов
  • Добавление водяные знаки
  • Добавление шифрование

Также следите за новым PyPDF4 пакетом, поскольку он, скорее всего, скоро заменитPyPDF2. Вы могли бы также хотеть проверить pdfrw, который может сделать много из тех же самых вещей, которые PyPDF2 может сделать.

Дальнейшее чтение

Если вы хотите узнать больше о работе с PDF-файлами в Python, вам следует воспользоваться некоторыми из следующих ресурсов для получения дополнительной информации:


Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram