Ajouter du texte à un PDF existant à l'aide de Python


107

Je dois ajouter du texte supplémentaire à un PDF existant en utilisant Python, quelle est la meilleure façon de procéder et quels modules supplémentaires dois-je installer.

Remarque: Idéalement, j'aimerais pouvoir l'exécuter à la fois sur Windows et Linux, mais à la fois, seul Linux fera l'affaire.

Edit: pyPDF et ReportLab ont l' air bien mais aucun ne me permettra de modifier un PDF existant, y a-t-il d'autres options?

Réponses:


88

Je sais que c'est un article plus ancien, mais j'ai passé beaucoup de temps à essayer de trouver une solution. J'en ai rencontré un décent en utilisant uniquement ReportLab et PyPDF, alors j'ai pensé partager:

  1. lisez votre PDF en utilisant PdfFileReader(), nous appellerons cette entrée
  2. créez un nouveau pdf contenant votre texte à ajouter à l'aide de ReportLab, enregistrez-le en tant qu'objet chaîne
  3. lire l'objet string en utilisant PdfFileReader(), nous appellerons ce texte
  4. créer un nouvel objet PDF en utilisant PdfFileWriter(), nous appellerons cette sortie
  5. Parcourez l' entrée et appliquez .mergePage(*text*.getPage(0))pour chaque page à laquelle vous souhaitez ajouter le texte, puis utilisez output.addPage()pour ajouter les pages modifiées à un nouveau document

Cela fonctionne bien pour les ajouts de texte simples. Voir l'exemple de PyPDF pour le filigrane d'un document.

Voici un code pour répondre à la question ci-dessous:

packet = StringIO.StringIO()
can = canvas.Canvas(packet, pagesize=letter)
<do something with canvas>
can.save()
packet.seek(0)
input = PdfFileReader(packet)

De là, vous pouvez fusionner les pages du fichier d'entrée avec un autre document.


2
"créez un nouveau pdf contenant votre texte à ajouter en utilisant ReportLab, enregistrez-le en tant qu'objet chaîne" Comment faites-vous cela? C'est une instance de canevas.
Lakshman Prasad

1
J'ai ajouté un exemple de code ci-dessus pour répondre à la question de Lakshman.
dwelch

Je recommande d'utiliser PyPDF2 car il est plus mis à jour, vérifiez également leur exemple de code: github.com/mstamy2/PyPDF2/blob/…
blaze

2
Ce code créera un nouveau fichier pdf et ignorera toutes les métadonnées. Il ne s'ajoute donc pas au pdf existant.
Anton Kukoba

125

Exemple pour [Python 2.7]:

from pyPdf import PdfFileWriter, PdfFileReader
import StringIO
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

packet = StringIO.StringIO()
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
can.drawString(10, 100, "Hello world")
can.save()

#move to the beginning of the StringIO buffer
packet.seek(0)
new_pdf = PdfFileReader(packet)
# read your existing PDF
existing_pdf = PdfFileReader(file("original.pdf", "rb"))
output = PdfFileWriter()
# add the "watermark" (which is the new pdf) on the existing page
page = existing_pdf.getPage(0)
page.mergePage(new_pdf.getPage(0))
output.addPage(page)
# finally, write "output" to a real file
outputStream = file("destination.pdf", "wb")
output.write(outputStream)
outputStream.close()

Exemple pour Python 3.x:


from PyPDF2 import PdfFileWriter, PdfFileReader
import io
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

packet = io.BytesIO()
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
can.drawString(10, 100, "Hello world")
can.save()

#move to the beginning of the StringIO buffer
packet.seek(0)
new_pdf = PdfFileReader(packet)
# read your existing PDF
existing_pdf = PdfFileReader(open("original.pdf", "rb"))
output = PdfFileWriter()
# add the "watermark" (which is the new pdf) on the existing page
page = existing_pdf.getPage(0)
page.mergePage(new_pdf.getPage(0))
output.addPage(page)
# finally, write "output" to a real file
outputStream = open("destination.pdf", "wb")
output.write(outputStream)
outputStream.close()

13
Pour python3, le paquet doit être io.BytesIOet utiliser PyPDF2 plutôt que pyPDF (qui n'est pas maintenu). Très bonne réponse!
Noufal Ibrahim

4
Merci d'avoir partagé. Cela fonctionne très bien. Une note: je pense qu'il vaut mieux utiliser openau lieu de file.
mitenka le

Je pense que c'est une réponse plus acceptable, d'autant plus qu'elle comprend un exemple concret.
Casey

1
Attention: le nouveau document ne comprend que la première page de l'original! Il est assez facile de copier le reste des pages de existing_pdfà output, l'exemple de code ne le fait pas.
alexis

@alexis: Comment modifieriez-vous le code pour mettre quelque chose sur la deuxième page du pdf? J'ai un formulaire qui utilise deux pages et je suis bloqué sur la première page. Merci d'avance.
DavidV

11

pdfrw vous permettra de lire des pages à partir d'un PDF existant et de les dessiner sur un canevas reportlab (comme pour dessiner une image). Il y a des exemples pour cela dans le sous-répertoire pdfrw examples / rl1 sur github. Avertissement: je suis l'auteur de pdfrw.


Je pense que vous pourriez mettre un lien là
The6thSense

Bon point! Je n'avais pas fait beaucoup de trucs SO quand j'ai posté ça, et j'étais préoccupé par la "politique de texte minimal plus lien". (Mon représentant n'avait que 46 ans à l'époque, et l'IIRC je venais de recevoir un -2 sur une réponse, donc j'étais un peu inquiet des nouvelles réponses à des questions de 5 ans :)
Patrick Maupin

les vieilles questions
reçoivent

FWIW, il y a d'autres exemples reportlab / pdfrw si vous commencez à suivre ce lien . J'ai répondu là, basé sur une réponse dans la cible dupe.
Patrick Maupin

7

En tirant parti de la réponse de David Dehghan ci-dessus, les travaux suivants fonctionnent en Python 2.7.13:

from PyPDF2 import PdfFileWriter, PdfFileReader, PdfFileMerger

import StringIO

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

packet = StringIO.StringIO()
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
can.drawString(290, 720, "Hello world")
can.save()

#move to the beginning of the StringIO buffer
packet.seek(0)
new_pdf = PdfFileReader(packet)
# read your existing PDF
existing_pdf = PdfFileReader("original.pdf")
output = PdfFileWriter()
# add the "watermark" (which is the new pdf) on the existing page
page = existing_pdf.getPage(0)
page.mergePage(new_pdf.getPage(0))
output.addPage(page)
# finally, write "output" to a real file
outputStream = open("destination.pdf", "wb")
output.write(outputStream)
outputStream.close()

3

cpdf fera le travail à partir de la ligne de commande. Ce n'est pas du python, cependant (afaik):

cpdf -add-text "Line of text" input.pdf -o output .pdf

0

Vous aurez peut-être plus de chance de résoudre le problème en convertissant le PDF en un format modifiable, en écrivant vos modifications, puis en le reconvertissant en PDF. Je ne connais pas de bibliothèque qui vous permet d'éditer directement un PDF mais il existe de nombreux convertisseurs entre DOC et PDF par exemple.


1
Le problème est que je n'ai que la source en PDF (d'un tiers) et PDF -> DOC -> PDF perdra beaucoup dans la conversion. J'ai également besoin de cela pour fonctionner sous Linux, donc DOC n'est peut-être pas le meilleur choix.
Frozenskys

Je pense qu'Adobe maintient la capacité d'édition de PDF assez fermée et propriétaire afin qu'ils puissent vendre des licences pour leurs meilleures versions d'Acrobat. Vous pouvez peut-être trouver un moyen d'automatiser l'utilisation d'Acrobat Pro pour le modifier, en utilisant une sorte d'interface de macro.
aehlke

Si les parties sur lesquelles vous voulez écrire sont des champs de formulaire, il existe des interfaces XML pour les éditer - sinon je ne trouve rien.
aehlke

Non, je voulais juste ajouter quelques lignes de texte à chaque page.
Frozenskys


-4

Avez-vous essayé pyPdf ?

Désolé, il n'a pas la possibilité de modifier le contenu d'une page.


On dirait que cela pourrait fonctionner, est-ce que quelqu'un l'a utilisé? À quoi ressemble l'utilisation de la mémoire?
Frozenskys

Il a la capacité d'ajouter un filigrane de texte et s'il était correctement formaté, cela pourrait fonctionner.
Frozenskys
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.