Comment travailler avec un PDF en Python

Comment travailler avec un PDF en Python

Le format PDF ou Portable Document Format est un format de fichier qui peut être utilisé pour présenter et échanger des documents de manière fiable entre les systèmes d'exploitation. Alors que le PDF a été inventé à l'origine par Adobe, c'est maintenant unopen standard qui est maintenu par l'Organisation internationale de normalisation (ISO). Vous pouvez travailler avec un PDF préexistant en Python en utilisant le packagePyPDF2.

PyPDF2 est un packagepure-Python que vous pouvez utiliser pour de nombreux types différents d'opérations PDF.

À la fin de cet article, vous saurez comment effectuer les opérations suivantes:

  • Extraire les informations d'un document à partir d'un PDF en Python

  • Faire pivoter les pages

  • Fusionner des PDF

  • Diviser les PDF

  • Ajouter des filigranes

  • Chiffrer un PDF

Commençons!

Free Bonus:Click here to get access to a chapter from Python Tricks: The Book qui vous montre les meilleures pratiques de Python avec des exemples simples que vous pouvez appliquer instantanément pour écrire du code + Pythonic plus beau.

Historique depyPdf,PyPDF2 etPyPDF4

Le package originalpyPdf a été publié en 2005. La dernière publication officielle depyPdf remonte à 2010. Après une période d'environ un an, une société appeléePhasit a sponsorisé une fourchette depyPdf appeléePyPDF2. Le code a été écrit pour être rétrocompatible avec l'original et a très bien fonctionné pendant plusieurs années, sa dernière version étant en 2016.

Il y a eu une brève série de versions d'un package appeléPyPDF3, puis le projet a été renommé enPyPDF4. Tous ces projets font à peu près la même chose, mais la plus grande différence entrepyPdf et PyPDF2 + est que ces dernières versions ont ajouté la prise en charge de Python 3. Il existe un fork de Python 3 différent despyPdf for Python 3d'origine, mais celui-ci n'a pas été maintenu depuis de nombreuses années.

Alors quePyPDF2 a été récemment abandonné, le nouveauPyPDF4 n'a pas une rétrocompatibilité totale avecPyPDF2. La plupart des exemples de cet article fonctionneront parfaitement avecPyPDF4, mais il y en a qui ne le peuvent pas, c'est pourquoiPyPDF4 n'est pas présenté plus en détail dans cet article. N'hésitez pas à échanger les importations contrePyPDF2 avecPyPDF4 et voyez comment cela fonctionne pour vous.

pdfrw: une alternative

Patrick Maupin a créé un package appelépdfrw qui peut faire beaucoup des mêmes choses quePyPDF2. Vous pouvez utiliserpdfrw pour tous les mêmes types de tâches que vous apprendrez à faire dans cet article pourPyPDF2, à l'exception notable du chiffrement.

La plus grande différence en ce qui concernepdfrw est qu'il s'intègre au packageReportLab afin que vous puissiez prendre un PDF préexistant et en créer un nouveau avec ReportLab en utilisant tout ou partie du PDF préexistant.

Installation

L'installation dePyPDF2 peut être effectuée avecpip ouconda si vous utilisez Anaconda au lieu de Python classique.

Voici comment installerPyPDF2 avecpip:

$ pip install pypdf2

L'installation est assez rapide carPyPDF2 n'a aucune dépendance. Vous passerez probablement autant de temps à télécharger le package que vous l'installerez.

Continuons et apprenons à extraire des informations d'un fichier PDF.

Comment extraire les informations d'un document à partir d'un PDF en Python

Vous pouvez utiliserPyPDF2 pour extraire des métadonnées et du texte d'un PDF. Cela peut être utile lorsque vous effectuez certains types d'automatisation sur vos fichiers PDF préexistants.

Voici les types actuels de données qui peuvent être extraites:

  • Auteur

  • Créateur

  • Producteur

  • Matière

  • Titre

  • Nombre de pages

Vous devez aller chercher un PDF à utiliser pour cet exemple. Vous pouvez utiliser n'importe quel PDF que vous avez à portée de main sur votre machine. Pour simplifier les choses, je suis allé àLeanpub et j'ai pris un échantillon d'un de mes livres pour cet exercice. L'échantillon que vous souhaitez télécharger s'appellereportlab-sample.pdf.

Écrivons du code à l'aide de ce PDF et apprenons comment vous pouvez accéder à ces attributs:

# 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)

Ici, vous importezPdfFileReader du packagePyPDF2. LePdfFileReader est une classe avec plusieurs méthodes pour interagir avec les fichiers PDF. Dans cet exemple, vous appelez.getDocumentInfo(), qui renverra une instance deDocumentInformation. Il contient la plupart des informations qui vous intéressent. Vous appelez également.getNumPages() sur l'objet lecteur, qui renvoie le nombre de pages du document.

Note: Ce dernier bloc de code utilise les nouvelles f-strings de Python 3 pour le formatage des chaînes. Si vous souhaitez en savoir plus, vous pouvez consulterPython 3’s f-Strings: An Improved String Formatting Syntax (Guide).

La variableinformation a plusieurs attributs d'instance que vous pouvez utiliser pour obtenir le reste des métadonnées que vous souhaitez du document. Vous imprimez ces informations et les retournez également pour une utilisation future potentielle.

Alors quePyPDF2 a.extractText(), qui peut être utilisé sur ses objets de page (non représentés dans cet exemple), cela ne fonctionne pas très bien. Certains PDF renvoient du texte et d'autres renvoient une chaîne vide. Lorsque vous souhaitez extraire du texte d'un PDF, vous devez plutôt consulter le projetPDFMiner. PDFMiner est beaucoup plus robuste et a été spécialement conçu pour extraire du texte à partir de PDF.

Vous êtes maintenant prêt à en savoir plus sur la rotation des pages PDF.

Comment faire pivoter les pages

Parfois, vous recevrez des fichiers PDF contenant des pages enlandscape mode au lieu du mode portrait. Ou peut-être qu'ils sont même à l'envers. Cela peut se produire lorsque quelqu'un numérise un document au format PDF ou par e-mail. Vous pouvez imprimer le document et lire la version papier ou vous pouvez utiliser la puissance de Python pour faire pivoter les pages incriminées.

Pour cet exemple, vous pouvez choisir un Real Pythonarticle et l'imprimer au format PDF.

Apprenons à faire pivoter certaines des pages de cet article avecPyPDF2:

# 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)

Pour cet exemple, vous devez importer lesPdfFileWriter en plus dePdfFileReader car vous devrez écrire un nouveau PDF. rotate_pages() prend le chemin vers le PDF que vous souhaitez modifier. Dans cette fonction, vous devrez créer un objet écrivain que vous pourrez nommerpdf_writer et un objet lecteur appelépdf_reader.

Ensuite, vous pouvez utiliser.GetPage() pour obtenir la page souhaitée. Ici, vous récupérez la page zéro, qui est la première page. Ensuite, vous appelez la méthode.rotateClockwise() de l'objet page et passez à 90 degrés. Ensuite, pour la page deux, vous appelez.rotateCounterClockwise() et passez-le également à 90 degrés.

Note: Le packagePyPDF2 vous permet uniquement de faire pivoter une page par incréments de 90 degrés. Sinon, vous recevrez unAssertionError.

Après chaque appel aux méthodes de rotation, vous appelez.addPage(). Cela ajoutera la version pivotée de la page à l'objet écrivain. La dernière page que vous ajoutez à l'objet écrivain est la page 3 sans aucune rotation.

Enfin, vous écrivez le nouveau PDF en utilisant.write(). Il prend unfile-like object comme paramètre. Ce nouveau PDF contiendra trois pages. Les deux premiers seront tournés dans des directions opposées et seront en paysage tandis que la troisième page est une page normale.

Voyons maintenant comment fusionner plusieurs PDF en un seul.

Comment fusionner des PDF

Il existe de nombreuses situations où vous souhaiterez prendre deux PDF ou plus et les fusionner en un seul PDF. Par exemple, vous pouvez avoir une page de garde standard qui doit passer à de nombreux types de rapports. Vous pouvez utiliser Python pour vous aider à faire ce genre de chose.

Pour cet exemple, vous pouvez ouvrir un PDF et imprimer une page en tant que PDF séparé. Recommencez ensuite, mais avec une autre page. Cela vous donnera quelques entrées à utiliser à des fins d'exemple.

Continuons et écrivons du code que vous pouvez utiliser pour fusionner des 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')

Vous pouvez utilisermerge_pdfs() lorsque vous avez une liste de fichiers PDF que vous souhaitez fusionner. Vous devrez également savoir où enregistrer le résultat, donc cette fonction prend une liste de chemins d'entrée et un chemin de sortie.

Ensuite, vous bouclez sur les entrées et créez un objet lecteur PDF pour chacune d'entre elles. Ensuite, vous parcourez toutes les pages du fichier PDF et utilisez.addPage() pour ajouter chacune de ces pages à elle-même.

Une fois que vous avez fini d'itérer sur toutes les pages de tous les PDF de votre liste, vous noterez le résultat à la fin.

Un élément que je voudrais souligner est que vous pouvez améliorer un peu ce script en ajoutant une plage de pages à ajouter si vous ne souhaitez pas fusionner toutes les pages de chaque PDF. Si vous souhaitez relever un défi, vous pouvez également créer une interface de ligne de commande pour cette fonction en utilisant le moduleargparse de Python.

Voyons comment faire le contraire de la fusion!

Comment diviser des PDF

Il y a des moments où vous pouvez avoir un PDF que vous devez diviser en plusieurs PDF. Cela est particulièrement vrai pour les PDF qui contiennent beaucoup de contenu numérisé, mais il existe une multitude de bonnes raisons de vouloir diviser un PDF.

Voici comment vous pouvez utiliserPyPDF2 pour diviser votre PDF en plusieurs fichiers:

# 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')

Dans cet exemple, vous créez à nouveau un objet de lecteur PDF et bouclez sur ses pages. Pour chaque page du PDF, vous allez créer une nouvelle instance de rédacteur PDF et y ajouter une seule page. Ensuite, vous écrirez cette page dans un fichier au nom unique. Une fois le script terminé, vous devez diviser chaque page du PDF d'origine en PDF distincts.

Voyons maintenant comment ajouter un filigrane à votre PDF.

Comment ajouter des filigranes

Les filigranes identifient des images ou des motifs sur des documents imprimés et numériques. Certains filigranes ne sont visibles que dans des conditions d'éclairage spéciales. La raison pour laquelle le filigrane est important est qu'il vous permet de protéger votre propriété intellectuelle, comme vos images ou vos PDF. Un autre terme pour filigrane est superposition.

Vous pouvez utiliser Python etPyPDF2 pour filigraner vos documents. Vous devez avoir un PDF contenant uniquement votre image ou texte en filigrane.

Voyons maintenant comment ajouter un filigrane:

# 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() accepte trois arguments:

  1. input_pdf: le chemin du fichier PDF à filigraner

  2. output: le chemin dans lequel vous souhaitez enregistrer la version filigranée du PDF

  3. watermark: un PDF contenant votre image ou texte de filigrane

Dans le code, vous ouvrez le PDF en filigrane et prenez uniquement la première page du document car c'est là que votre filigrane doit résider. Ensuite, vous créez un objet lecteur PDF en utilisant lesinput_pdf et un objet génériquepdf_writer pour écrire le PDF filigrané.

L'étape suivante consiste à parcourir les pages dans lesinput_pdf. C'est là que la magie opère. Vous devrez appeler.mergePage() et lui transmettre leswatermark_page. Lorsque vous faites cela, il superposera leswatermark_page en haut de la page actuelle. Ensuite, vous ajoutez cette page nouvellement fusionnée à votre objetpdf_writer.

Enfin, vous écrivez le nouveau PDF en filigrane sur le disque et vous avez terminé!

Le dernier sujet que vous apprendrez est la façon dontPyPDF2 gère le chiffrement.

Comment crypter un PDF

PyPDF2 ne prend actuellement en charge que l'ajout d'un mot de passe utilisateur et d'un mot de passe propriétaire à un PDF préexistant. Dans PDF Land, un mot de passe propriétaire vous donnera essentiellement des privilèges d'administrateur sur le PDF et vous permettra de définir des autorisations sur le document. D'un autre côté, le mot de passe utilisateur vous permet simplement d'ouvrir le document.

Pour autant que je sache,PyPDF2 ne vous permet pas de définir d’autorisations sur le document, même s’il vous permet de définir le mot de passe du propriétaire.

Quoi qu'il en soit, voici comment vous pouvez ajouter un mot de passe, qui cryptera également le PDF de manière inhérente:

# 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() prend les chemins d'accès PDF d'entrée et de sortie ainsi que le mot de passe que vous souhaitez ajouter au PDF. Il ouvre ensuite un écrivain PDF et un objet lecteur, comme précédemment. Étant donné que vous souhaiterez crypter l'intégralité du PDF d'entrée, vous devrez parcourir toutes ses pages et les ajouter à l'auteur.

La dernière étape consiste à appeler.encrypt(), qui prend le mot de passe de l'utilisateur, le mot de passe du propriétaire et si oui ou non un cryptage de 128 bits doit être ajouté. Par défaut, le cryptage 128 bits doit être activé. Si vous le définissez surFalse, le cryptage 40 bits sera appliqué à la place.

Le cryptage PDF deNote: utilise RC4 ou AES (Advanced Encryption Standard) pour crypter le PDF selonpdflib.com.

Ce n'est pas parce que vous avez chiffré votre PDF qu'il est nécessairement sécurisé. Il existe des outils pour supprimer les mots de passe des PDF. Si vous souhaitez en savoir plus, l’Université Carnegie Mellon a unpaper on the topic intéressant.

Conclusion

Le packagePyPDF2 est assez utile et est généralement assez rapide. Vous pouvez utiliserPyPDF2 pour automatiser les gros travaux et tirer parti de ses capacités pour vous aider à mieux faire votre travail!

Dans ce didacticiel, vous avez appris à effectuer les opérations suivantes:

  • Extraire les métadonnées d'un PDF

  • Faire pivoter les pages

  • Fusionner et fractionner des PDF

  • Ajouter des filigranes

  • Ajouter un cryptage

Gardez également un œil sur le nouveau packagePyPDF4 car il remplacera probablementPyPDF2 bientôt. Vous pouvez également consulterpdfrw, qui peut faire beaucoup des mêmes choses quePyPDF2 peut faire.

Lectures complémentaires

Si vous souhaitez en savoir plus sur l'utilisation des fichiers PDF en Python, vous devriez consulter certaines des ressources suivantes pour plus d'informations: