Dodaj tekst do istniejącego pliku PDF za pomocą Pythona

107

Muszę dodać trochę tekstu do istniejącego pliku PDF za pomocą Pythona, jak najlepiej to zrobić i jakie dodatkowe moduły będę musiał zainstalować.

Uwaga: Idealnie chciałbym móc to uruchomić zarówno na Windowsie, jak i na Linuksie, ale w trybie push wystarczy tylko Linux.

Edycja: pyPDF i ReportLab wyglądają dobrze, ale żaden z nich nie pozwoli mi edytować istniejącego pliku PDF, czy są jakieś inne opcje?

Frozenskys
źródło

Odpowiedzi:

88

Wiem, że to starszy post, ale spędziłem dużo czasu próbując znaleźć rozwiązanie. Natknąłem się na przyzwoity, używając tylko ReportLab i PyPDF, więc pomyślałem, że podzielę się:

  1. czytaj swój plik PDF za pomocą PdfFileReader(), nazwiemy to wejście
  2. utwórz nowy plik PDF zawierający tekst do dodania za pomocą ReportLab, zapisz go jako obiekt ciągu
  3. czytaj obiekt string używając PdfFileReader(), nazwiemy ten tekst
  4. utwórz nowy obiekt PDF za pomocą PdfFileWriter(), nazwiemy to wyjście
  5. iteruj przez dane wejściowe i stosuj .mergePage(*text*.getPage(0))dla każdej strony, do której chcesz dodać tekst, a następnie użyj, output.addPage()aby dodać zmodyfikowane strony do nowego dokumentu

Działa to dobrze w przypadku prostych dodatków tekstowych. Zobacz próbkę PyPDF dotyczącą znakowania wodnego dokumentu.

Oto kod odpowiadający na poniższe pytanie:

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

Stąd możesz połączyć strony pliku wejściowego z innym dokumentem.

dwelch
źródło
2
„utwórz nowy plik PDF zawierający tekst do dodania za pomocą ReportLab, zapisz to jako obiekt tekstowy” Jak to zrobić? To instancja płótna.
Lakshman Prasad
1
Dodałem powyżej przykładowy kod, aby odpowiedzieć na pytanie Lakshmana.
dwelch
Polecam używanie PyPDF2, ponieważ jest bardziej zaktualizowane, sprawdź także ich przykładowy kod: github.com/mstamy2/PyPDF2/blob/ ...
blaze
2
Ten kod utworzy nowy plik pdf i pominie wszystkie metadane. Więc nie jest dołączany do istniejącego pliku PDF.
Anton Kukoba
125

Przykład dla [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()

Przykład dla Pythona 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()
David Dehghan
źródło
13
W przypadku python3 pakiet powinien być io.BytesIOi używać raczej PyPDF2 niż pyPDF (który jest nieobsługiwany). Świetna odpowiedź!
Noufal Ibrahim
4
Dzięki za udostępnienie. Działa świetnie. Jedna uwaga: uważam, że lepiej jest używać openzamiast file.
mitenka
Uważam, że jest to bardziej akceptowalna odpowiedź, zwłaszcza że zawiera praktyczny przykład.
Casey
1
Uwaga: nowy dokument zawiera tylko pierwszą stronę oryginału! Wystarczy skopiować pozostałe strony z existing_pdfdo output, przykładowy kod po prostu nie.
alexis
@alexis: Jak zmodyfikowałbyś kod, aby umieścić coś na drugiej stronie pliku PDF? Mam formularz, który używa dwóch stron i utknąłem na pierwszej stronie. Z góry dziękuję.
DavidV
11

pdfrw pozwoli ci czytać strony z istniejącego pliku PDF i narysować je na kanwie reportlab (podobnie do rysowania obrazu). Przykłady tego można znaleźć w podkatalogu pdfrw examples / rl1 na github. Zastrzeżenie: jestem autorem pdfrw.

Patrick Maupin
źródło
Myślę, że możesz umieścić tam link
The6thSense
Słuszna uwaga! Nie zrobiłem zbyt wiele rzeczy, kiedy to opublikowałem i martwiłem się o zasady „minimalnego tekstu i linków”. (Mój przedstawiciel miał wtedy tylko 46 lat, a IIRC właśnie otrzymałem -2 przy jednej odpowiedzi, więc trochę się martwiłem nowymi odpowiedziami na pytania od 5 lat :)
Patrick Maupin
stare pytania
zyskują
FWIW, jest więcej przykładów reportlab / pdfrw, jeśli zaczniesz podążać za tym linkiem . Odpowiedziałem tam, opierając się na odpowiedzi w fałszywym celu.
Patrick Maupin
7

Wykorzystując David Dehghan jest odpowiedź powyżej, następujące prace w Pythonie 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()
Ross Smith II
źródło
3

cpdf wykona zadanie z wiersza poleceń. Jednak to nie jest Python (afaik):

cpdf -add-text "Line of text" input.pdf -o output .pdf
user2243670
źródło
0

Możesz mieć więcej szczęścia, rozkładając problem i konwertując plik PDF na format edytowalny, zapisując zmiany, a następnie konwertując je z powrotem do formatu PDF. Nie znam biblioteki, która umożliwia bezpośrednią edycję plików PDF, ale na przykład istnieje wiele konwerterów między DOC i PDF.

aehlke
źródło
1
Problem polega na tym, że mam źródło tylko w formacie PDF (od strony trzeciej), a PDF -> DOC -> PDF wiele straci podczas konwersji. Potrzebuję tego również do działania w systemie Linux, więc DOC może nie być najlepszym wyborem.
Frozenskys
Uważam, że Adobe utrzymuje możliwość edycji PDF dość zamkniętą i zastrzeżoną, aby mogła sprzedawać licencje na swoje lepsze wersje programu Acrobat. Może uda Ci się zautomatyzować użycie programu Acrobat Pro do jego edycji za pomocą jakiegoś interfejsu makr.
aehlke
Jeśli części, w których chcesz pisać, są polami formularzy, są interfejsy XML do ich edycji - w przeciwnym razie nie mogę nic znaleźć.
aehlke
Nie, chciałem tylko dodać kilka wierszy tekstu do każdej strony.
Frozenskys
0

Jeśli korzystasz z systemu Windows, może to zadziałać:

Program pilotażowy PDF Creator

Istnieje również oficjalny dokument dotyczący struktury tworzenia i edycji plików PDF w języku Python. Jest trochę przestarzały, ale może może dać ci przydatne informacje:

Używanie Pythona jako struktury do edycji i przetwarzania PDF

thedz
źródło
Biała księga wygląda dobrze, ale zawiera trochę światła na temat kodu i tak naprawdę nie mam zasobów, aby samodzielnie wdrożyć całą strukturę PDF! ;)
Frozenskys
-4

Czy próbowałeś / aś pyPdf ?

Przepraszamy, nie ma możliwości modyfikowania treści strony.

Zoman
źródło
Wygląda na to, że to zadziała, czy ktoś z tego korzystał? Jakie jest zużycie pamięci?
Frozenskys
Ma możliwość dodania tekstowego znaku wodnego i jeśli został poprawnie sformatowany, może działać.
Frozenskys