Переносимый формат документа или PDF - это формат файла, который можно использовать для надежного представления и обмена документами в операционных системах. Хотя PDF изначально был изобретен Adobe, сейчас это открытый стандарт, который поддерживается Международной организацией по стандартизации (ISO). Вы можете работать с уже существующим PDF в Python, используя пакет PyPDF2.
PyPDF2 - это пакет на чистом Python, который вы можете использовать для различных типов операций PDF.
К концу этой статьи вы будете знать, как сделать следующее:
- Извлечение информации о документе из PDF в Python
- Поворот страниц
- Объединить PDF-файлы
- Разделить PDF-файлы
- Добавить водяные знаки
- Зашифровать PDF
Давайте начнем!
История pyPdf, PyPDF2 и PyPDF4
Оригинальный пакет pyPdf был выпущен еще в 2005 году. Последний официальный выпуск pyPdf был в 2010 году. По прошествии примерно года компания Phasit спонсировала выпуск pyPdf под названием PyPDF2. Код был написан для обратной совместимости с оригиналом и работал довольно хорошо в течение нескольких лет, последний выпуск был в 2016 году.
Была краткая серия выпусков пакета под названием PyPDF3, а затем проект был переименован в PyPDF4. Все эти проекты делают одно и то же, но самое большое различие между pyPdf и PyPDF2 + заключается в том, что в последних версиях добавлена поддержка Python 3. Существует другая ветка Python 3 исходного pyPdf для Python 3, но она не поддерживалась в течение многих лет.
Хотя PyPDF2 недавно был заброшен, новый PyPDF4 не имеет полной обратной совместимости с PyPDF2. Большинство примеров в этой статье будут прекрасно работать с PyPDF4, но есть и такие, которые не могут, поэтому PyPDF4 не рассматривается в этой статье более подробно. Не стесняйтесь поменять местами импорт для PyPDF2 с PyPDF4 и посмотрите, как он работает для вас.
pdfrw: альтернатива
Patrick Maupin создал пакет под названием 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, который возвращает количество страниц в документе.
Информационная переменная имеет несколько атрибутов экземпляра, которые вы можете использовать для получения остальных метаданных, которые вы хотите получить из документа. Вы распечатываете эту информацию, а также возвращаете ее для будущего использования.
В то время как PyPDF2 имеет .extractText (), который может использоваться на объектах его страниц (не показанных в этом примере), он работает не очень хорошо. Некоторые PDF-файлы будут возвращать текст, а некоторые - пустую строку. Если вы хотите извлечь текст из PDF, вы должны вместо этого проверить проект PDFMiner. 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(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 градусов.
После каждого вызова методов ротации вы вызываете .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-файла. Если вам нужен вызов, вы также можете создать интерфейс командной строки для этой функции с помощью модуля Python 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-файлы. Другой термин для водяного знака - наложение.
Вы можете использовать Python и 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 () принимает три аргумента:
- input_pdf: путь к файлу PDF с водяным знаком
- вывод: путь, по которому вы хотите сохранить версию PDF с водяным знаком
- водяной знак: PDF, содержащий изображение или текст водяного знака
В коде вы открываете водяной знак PDF и берете только первую страницу документа, поскольку именно там должен находиться ваш водяной знак. Затем вы создаете объект для чтения PDF, используя input_pdf и общий объект pdf_writer для записи PDF с водяными знаками.
Следующим шагом является перебор страниц в файле input_pdf. Здесь происходит волшебство. Вам нужно будет вызвать .mergePage () и передать ему 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-битное шифрование.
Заключение
Пакет PyPDF2 довольно полезен и обычно довольно быстр. Вы можете использовать PyPDF2 для автоматизации больших заданий и использовать его возможности, чтобы помочь вам лучше выполнять свою работу!