Рубрики
Без рубрики

Введение в pypdf2

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Pypdf2 Пакет – это библиотека Pure-Python PDF, которую вы можете использовать для разделения, объединения, обрезки и преобразования страниц в ваших PDF. Согласно веб-сайте PYPDF2, вы также можете использовать PypDF2 для добавления данных, параметров просмотра и паролей в PDFS. Наконец, вы можете использовать PypDF2 для извлечения текста и метаданных из ваших PDF.

PypDF2 на самом деле является вилкой исходного pypdf, который был написан Mathiew Fenniak и выпущен в 2005 году. Однако первоначальный последний выпуск Pypdf был в 2014 году. Компания под названием Pastemit, Inc, говорила с Mathieu и завершила спонсирование PYPDF2 в качестве вилки Pypdf

На момент написания этой книги пакет PypDF2 не имел выпуска с 2016 года. Однако он все еще является твердым и полезным пакетом, который стоит вашего времени, чтобы узнать.

Следующие списки о том, что мы будем изучать в этой статье:

  • Извлечение метаданных
  • Разделение документов
  • Объединение 2 PDF файлов в 1
  • Вращающиеся страницы
  • Наложение/водяные знаки
  • Шифрование/расшифровка

Давайте начнем с учета того, как установить PypDF2!

Монтаж

PYPDF2 – это чистый пакет Python, поэтому вы можете установить его, используя PIP (при условии, что PIP находится на пути вашей системы):

python -m pip install pypdf2

Как обычно, вы должны установить 3-я пакеты Python Python в виртуальную среду Python, чтобы убедиться, что она работает так, как вы хотите.

Извлечение метаданных из PDFS

Вы можете использовать PYPDF2 для извлечения справедливого количества полезных данных из любого PDF. Например, вы можете узнать автор документа, его названия и предмета и сколько страниц есть. Давайте узнаем, как загрузив образец этой книги из Ленпуб Отказ Образец я загружал было названо «REPORTLAB-образец.PDF». Я включу этот PDF для вас, чтобы использовать в исходном коде GitHub.

Вот код:

# get_doc_info.py

from PyPDF2 import PdfFileReader


def get_info(path):
    with open(path, 'rb') as f:
        pdf = PdfFileReader(f)
        info = pdf.getDocumentInfo()
        number_of_pages = pdf.getNumPages()
    
    print(info)

    author = info.author
    creator = info.creator
    producer = info.producer
    subject = info.subject
    title = info.title

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

Здесь мы импортируем Pdffilereader класс от Pypdf2 Отказ Этот класс дает нам возможность читать PDF и извлечь данные из него с использованием различных методов доступа. Первое, что мы делаем, это создать наши собственные get_info Функция, которая принимает пункт файла PDF в качестве единственного аргумента. Затем мы открываем файл в двоичном режиме только для чтения. Затем мы передаем этот обработчик файлов в PDFFILEREAREADER и создать его экземпляр.

Теперь мы можем извлечь некоторую информацию из PDF, используя getdocumentinfo метод. Это вернет экземпляр Pypdf2.pdf.documentinformation , который имеет следующие полезные атрибуты, среди прочего:

  • автор
  • создатель
  • режиссер
  • предмет
  • заглавие

Если вы распечатаете объект DocumentInformation, это то, что вы увидите:

{'/Author': 'Michael Driscoll',
 '/CreationDate': "D:20180331023901-00'00'",
 '/Creator': 'LaTeX with hyperref package',
 '/Producer': 'XeTeX 0.99998',
 '/Title': 'ReportLab - PDF Processing with Python'}

Мы также можем получить количество страниц в PDF, позвонив GetNUpages метод.

Извлечение текста из PDFS

PypDF2 имеет ограниченную поддержку для извлечения текста из PDFS. Это не имеет встроенной поддержки для извлечения изображений, к сожалению. Я видел некоторые рецепты в StackoverFlow, используя PypDF2 для извлечения изображений, но примеры кода, кажется, довольно удары или пропускают.

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

# extracting_text.py

from PyPDF2 import PdfFileReader


def text_extractor(path):
    with open(path, 'rb') as f:
        pdf = PdfFileReader(f)

        # get the first page
        page = pdf.getPage(1)
        print(page)
        print('Page type: {}'.format(str(type(page))))

        text = page.extractText()
        print(text)


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

Вы отметите, что этот код запускается почти так же, как наш предыдущий пример. Нам все еще нужно создать экземпляр Pdffilereader Отказ Но на этот раз мы снимаем страницу, используя GetPage метод. Pypdf2 – это нулевой, очень похоже на большинство вещей в Python, поэтому, когда вы передаете его, он фактически захватывает вторую страницу. Первая страница в этом случае это просто изображение, поэтому у него не будет никакого текста.

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

Чтобы получить этот пример код для работы, вам нужно будет пытаться запустить его против другого PDF. Я нашел один на веб-сервисе внутренних доходов Соединенных Штатов здесь: https://www.irs.gov/pub/irs-pdf/fw9.pdf.

Это форма W9 для людей, которые являются самозанятыми или сотрудниками контракта. Он также может быть использован в других ситуациях. Во всяком случае, я скачал его как W9.PDF Отказ Если вы используете это PDF вместо образец один, он будет счастливо извлекать некоторый текст с страницы 2. Я не буду воспроизвести вывод здесь, так как это довольно длинно.

Разделение PDFS.

Пакет PypDF2 дает вам возможность разбить один PDF в несколько. Вам просто нужно сказать, сколько вам нужных страниц. Для этого примера мы откроем PDF W9 из предыдущего примера и цикла по всему шести ее страницах. Мы расценимся с каждой страницы и превратим его в свой автономный PDF.

Давайте узнаем, как:

# pdf_splitter.py

import os
from PyPDF2 import PdfFileReader, PdfFileWriter


def pdf_splitter(path):
    fname = os.path.splitext(os.path.basename(path))[0]
    
    pdf = PdfFileReader(path)
    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter()
        pdf_writer.addPage(pdf.getPage(page))

        output_filename = '{}_page_{}.pdf'.format(
            fname, page+1)
        
        with open(output_filename, 'wb') as out:
            pdf_writer.write(out)
            
        print('Created: {}'.format(output_filename))

if __name__ == '__main__':
    path = 'w9.pdf'
    pdf_splitter(path)

Для этого примера нам нужно импортировать как Pdffilereader и PdffileWriter Отказ Тогда мы создаем забавную маленькую функцию под названием pdf_splitter Отказ Это принимает путь ввода PDF. Первая строка этой функции будет схватить имя входного файла, минус расширение. Далее мы открываем PDF вверх и создаем объект Reader. Затем мы зацикливаем все страницы, используя объект Reader GetNUpages метод.

Внутри для Цикл, мы создаем экземпляр PdffileWriter Отказ Затем мы добавляем страницу на нашем объекте Writer, используя его addpage . метод. Этот метод принимает объект страницы, поэтому чтобы получить объект страницы, мы называем объект Reader GetPage метод. Теперь мы добавили одну страницу к нашему объекту писателя. Следующим шагом является создание уникального имени файла, которое мы делаем с помощью исходного имени файла плюс слово «Page», а также номер страницы + 1. Мы добавляем, что номера страниц Pypdf2 находятся на нуля, поэтому страница 0 на самом деле Страница 1.

Наконец мы открываем новое имя файла в бинарном режиме и используем объект PDF Writer Написать Метод для записи содержимого объекта на диск.

Объединение нескольких PDF вместе

Теперь, когда у нас есть куча PDFS, давайте узнаем, как мы можем принять их и объединить их вместе. Одно полезное использование для этого является для предприятий, чтобы объединить свои капли в одном PDF. Мне нужно было объединить PDF для работы и для развлечения. Один проект, который прилипает в моем уме – это сканирование документов. В зависимости от того, что у вас есть сканер, вы можете в конечном итоге сканирование документа на несколько PDF-файлов, поэтому возможность присоединиться к ним вместе, может быть замечательным.

Когда исчезли оригинал Pypdf, единственный способ получить его, чтобы объединить несколько PDFS вместе, было похоже:

# pdf_merger.py

import glob
from PyPDF2 import PdfFileWriter, PdfFileReader

def merger(output_path, input_paths):
    pdf_writer = PdfFileWriter()
            
    for path in input_paths:
        pdf_reader = PdfFileReader(path)
        for page in range(pdf_reader.getNumPages()):
            pdf_writer.addPage(pdf_reader.getPage(page))
        
    with open(output_path, 'wb') as fh:
        pdf_writer.write(fh)
        
        
if __name__ == '__main__':
    paths = glob.glob('w9_*.pdf')
    paths.sort()
    merger('pdf_merger.pdf', paths)

Здесь мы создаем PdffileWriter объект и несколько Pdffilereader объекты. Для каждого PDF-пути мы создаем Pdffilereader Объект, а затем петля по его страницам, добавляя каждую страницу на нашем объекте писателя. Затем мы выписываем содержимое объекта Writer на диск.

Pypdf2 сделал это немного проще, создав Pdffilemerger класс:

# pdf_merger2.py

import glob
from PyPDF2 import PdfFileMerger

def merger(output_path, input_paths):
    pdf_merger = PdfFileMerger()
    file_handles = []
    
    for path in input_paths:
        pdf_merger.append(path)
        
    with open(output_path, 'wb') as fileobj:
        pdf_merger.write(fileobj)
        
if __name__ == '__main__':
    paths = glob.glob('fw9_*.pdf')
    paths.sort()
    merger('pdf_merger2.pdf', paths)

Здесь нам просто нужно создать Pdffilemerger Объект, а затем петлю через пути PDF, добавляя их в наш объект слияния. PYPDF2 автоматически добавит весь документ, чтобы вам не нужно питаться через все страницы каждого документа. Тогда мы просто пишем это на диск.

Pdffilemerger Класс также имеет слияние Метод, который вы можете использовать. Это определение кода выглядит так:

def merge(self, position, fileobj, bookmark=None, pages=None, 
          import_bookmarks=True):
        """
        Merges the pages from the given file into the output file at the
        specified page number.

        :param int position: The *page number* to insert this file. File will
            be inserted after the given number.

        :param fileobj: A File Object or an object that supports the standard 
            read and seek methods similar to a File Object. Could also be a
            string representing a path to a PDF file.

        :param str bookmark: Optionally, you may specify a bookmark to be 
            applied at the beginning of the included file by supplying the 
            text of the bookmark.

        :param pages: can be a :ref:`Page Range ` or a 
        ``(start, stop[, step])`` tuple
            to merge only the specified range of pages from the source
            document into the output document.

        :param bool import_bookmarks: You may prevent the source 
        document's bookmarks from being imported by specifying this as 
        ``False``.
        """

В основном метод Merge позволяет вам сказать PypDF, где объединить страницу по номеру страницы. Поэтому, если вы создали объект слияния с 3 страницами в нем, вы можете сказать объект слияния, чтобы объединить следующий документ в определенной позиции. Это позволяет разработчику сделать некоторые довольно сложные слияние операций. Попробуйте посмотрите, что вы можете сделать!

Вращающиеся страницы

PYPDF2 дает вам возможность вращать страницы. Однако вы должны вращаться на 90 градусов. Вы можете повернуть PDF-страницы по часовой стрелке, либо против часовой стрелки. Вот простой пример:

# pdf_rotator.py

from PyPDF2 import PdfFileWriter, PdfFileReader

def rotator(path):
    pdf_writer = PdfFileWriter()
    pdf_reader = PdfFileReader(path)
    
    page1 = pdf_reader.getPage(0).rotateClockwise(90)
    pdf_writer.addPage(page1)
    page2 = pdf_reader.getPage(1).rotateCounterClockwise(90)
    pdf_writer.addPage(page2)
    pdf_writer.addPage(pdf_reader.getPage(2))
    
    with open('pdf_rotator.pdf', 'wb') as fh:
        pdf_writer.write(fh)
        
if __name__ == '__main__':
    rotator('reportlab-sample.pdf')

Здесь мы создаем наш PDF-читатель и объекты писателя как раньше. Затем мы получаем первые и вторые страницы PDF, в котором мы прошли. Мы поворачиваем первую страницу 90 градусов по часовой стрелке или справа. Затем мы поворачиваем вторую страницу против часовой стрелки. Наконец, мы добавляем третью страницу в обычной ориентации к объекту Writer и выписываем нашу новую 3-страницу PDF-файл.

Если вы откроете PDF, вы обнаружите, что первые две страницы теперь вращаются в противоположных направлениях друг друга с третьей страницей в своей обычной ориентации.

Наложение/водяные знаки

PypDF2 также поддерживает объединение PDF-страницы вместе или наложение страниц друг на друга. Это может быть полезно, если вы хотите водить страницы в свой PDF. Например, одна из дистрибьюторов электронных книг, которые я использую, будет «Watermark» версии PDF моей книги с адресом электронной почты покупателя. Другое использование случая, которое я видел, чтобы я видел, чтобы добавить метки управления принтера на край страницы, чтобы сказать принтер, когда определенный документ достиг своего конца.

Для этого примера мы возьмем один из логотипов, которые я использую для моего блога, «мышь против Python», и накладывайте его поверх формы W9 из более раннего:

# watermarker.py

from PyPDF2 import PdfFileWriter, PdfFileReader


def watermark(input_pdf, output_pdf, watermark_pdf):
    watermark = PdfFileReader(watermark_pdf)
    watermark_page = watermark.getPage(0)
    
    pdf = PdfFileReader(input_pdf)
    pdf_writer = PdfFileWriter()
    
    for page in range(pdf.getNumPages()):
        pdf_page = pdf.getPage(page)
        pdf_page.mergePage(watermark_page)
        pdf_writer.addPage(pdf_page)
    
    with open(output_pdf, 'wb') as fh:
        pdf_writer.write(fh)
        
if __name__ == '__main__':
    watermark(input_pdf='w9.pdf', 
              output_pdf='watermarked_w9.pdf',
              watermark_pdf='watermark.pdf')

Первое, что мы делаем здесь, – извлекать страницу Watermark из PDF. Затем мы открываем PDF, которую мы хотим применить водяной знак. Мы используем для цикл, чтобы повторить на каждой из своих страниц и позвонить в объект страницы Mergepage Способ применения водяного знака. Далее мы добавляем, что Watermarked Page на наш объект PDF Writer. После того, как петли заканчивается, мы пишем наша новая версия Watermarked на диск.

Вот как выглядела первая страница:

Это было довольно легко.

Шифрование PDF

Пакет PypDF2 также поддерживает добавление пароля и шифрования к существующим формам PDF. Как вы можете вспомнить из главы 10, PDFS поддерживает пароль пользователя и пароль владельца. Пароль пользователя позволяет пользователю открывать и прочитать PDF, но может иметь некоторые ограничения, применяемые к PDF, которые могут помешать пользователю печатать, например. Насколько я могу сказать, вы не можете на самом деле нельзя применить какие-либо ограничения, используя PYPDF2, или он просто не задокументирован.

Вот как добавить пароль в PDF с PYPDF2:

# pdf_encryption.py

from PyPDF2 import PdfFileWriter, PdfFileReader

def encrypt(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__':
    encrypt(input_pdf='reportlab-sample.pdf',
            output_pdf='encrypted.pdf',
            password='blowfish')

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

Обертывание

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

Связанное чтение