Adicionar texto a PDF existente usando Python

107

Preciso adicionar algum texto extra a um PDF existente usando Python, qual é a melhor maneira de fazer isso e quais módulos extras vou precisar instalar.

Nota: Idealmente, eu gostaria de poder executar isso no Windows e no Linux, mas em um push o Linux só funcionará.

Editar: pyPDF e ReportLab parecem bons, mas nenhum deles me permite editar um PDF existente, há alguma outra opção?

Frozenskys
fonte

Respostas:

88

Eu sei que este é um post mais antigo, mas passei muito tempo tentando encontrar uma solução. Encontrei um decente usando apenas ReportLab e PyPDF, então pensei em compartilhar:

  1. leia seu PDF usando PdfFileReader(), vamos chamar essa entrada
  2. crie um novo pdf contendo seu texto para adicionar usando ReportLab, salve-o como um objeto string
  3. leia o objeto string usando PdfFileReader(), vamos chamar este texto
  4. criar um novo objeto PDF usando PdfFileWriter(), vamos chamar essa saída
  5. iterar por meio de entrada e aplicar .mergePage(*text*.getPage(0))para cada página à qual deseja que o texto seja adicionado, em seguida, use output.addPage()para adicionar as páginas modificadas a um novo documento

Isso funciona bem para adições de texto simples. Consulte o exemplo do PyPDF para marcar um documento com marca d'água.

Aqui está um código para responder à pergunta abaixo:

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

A partir daqui, você pode mesclar as páginas do arquivo de entrada com outro documento.

dwelch
fonte
2
"crie um novo pdf contendo seu texto para adicionar usando ReportLab, salve isso como um objeto de string" Como você faz isso? É uma instância do canvas.
Lakshman Prasad
1
Eu adicionei alguns códigos de amostra acima para responder à pergunta de Lakshman.
dwelch
Eu recomendo usar o PyPDF2, pois é mais atualizado, verifique também o código de amostra: github.com/mstamy2/PyPDF2/blob/…
blaze
2
Este código irá criar um novo arquivo pdf e irá pular todos os metadados. Portanto, não é anexado ao pdf existente.
Anton Kukoba,
125

Exemplo para [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()

Exemplo para 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()
David Dehghan
fonte
13
Para python3, o pacote deve ser io.BytesIOe usar PyPDF2 em vez de pyPDF (que não tem manutenção). Ótima resposta!
Noufal Ibrahim
4
Obrigado por compartilhar. Funciona muito bem. Uma observação: acredito que seja melhor usar em openvez de file.
mitenka
Eu acredito que esta é uma resposta mais aceitável, especialmente porque inclui um exemplo prático.
Casey de
1
Atenção: O novo documento inclui apenas a primeira página do original! É fácil copiar o resto das páginas de existing_pdfpara output, o código de exemplo simplesmente não o faz.
alexis
@alexis: Como você modificaria o código para colocar algo na segunda página do pdf? Tenho um formulário que usa duas páginas e estou preso na primeira página. Desde já, obrigado.
DavidV
11

O pdfrw permite que você leia páginas de um PDF existente e desenhe-as em uma tela de reportlab (semelhante a desenhar uma imagem). Existem exemplos para isso no subdiretório pdfrw examples / rl1 no github. Aviso: eu sou o autor do pdfrw.

Patrick Maupin
fonte
Acho que você poderia colocar um link lá
The6thSense
Bom ponto! Eu não tinha feito muito SO quando postei isso e estava preocupado com a "política de texto mais link mínimo". (Meu representante tinha apenas 46 anos na época, e IIRC I tinha acabado de receber -2 em uma resposta, então eu estava um pouco preocupado com as novas respostas para perguntas de 5 anos :)
Patrick Maupin
perguntas antigas recebem mais visualização :) e atenção
The6thSense
FWIW, existem mais alguns exemplos reportlab / pdfrw se você começar a seguir este link . Eu respondi lá, com base em uma resposta no alvo ingênuo.
Patrick Maupin de
7

Aproveitando a resposta de David Dehghan acima, o seguinte funciona no 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()
Ross Smith II
fonte
3

cpdf fará o trabalho a partir da linha de comando. Porém, não é python (afaik):

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

Você pode ter mais sorte dividindo o problema convertendo PDF em um formato editável, escrevendo suas alterações e, em seguida, convertendo-o novamente em PDF. Não conheço uma biblioteca que permite editar PDFs diretamente, mas existem muitos conversores entre DOC e PDF, por exemplo.

aehlke
fonte
1
O problema é que só tenho o código fonte em PDF (de terceiros) e PDF -> DOC -> PDF vai perder muito na conversão. Também preciso que funcione no Linux, portanto, DOC pode não ser a melhor escolha.
Frozenskys
Acredito que a Adobe mantém a capacidade de edição de PDF bastante fechada e proprietária para que possam vender licenças para suas melhores versões do Acrobat. Talvez você possa encontrar uma maneira de automatizar o uso do Acrobat Pro para editá-lo, usando algum tipo de interface de macro.
aehlke
Se as partes que você deseja escrever são campos de formulário, existem interfaces XML para editá-los - caso contrário, não consigo encontrar nada.
aehlke
Não, eu só queria adicionar algumas linhas de texto a cada página.
Frozenskys
0

Se você estiver no Windows, isso pode funcionar:

PDF Creator Pilot

Há também um white paper de uma estrutura de criação e edição de PDF em Python. É um pouco desatualizado, mas talvez possa lhe dar algumas informações úteis:

Usando Python como estrutura de edição e processamento de PDF

thedz
fonte
O white paper parece bom, mas é um pouco leve no código, e eu realmente não tenho os recursos para implementar um framework PDF inteiro sozinho! ;)
Frozenskys
-4

Você já experimentou o pyPdf ?

Desculpe, não tem a capacidade de modificar o conteúdo de uma página.

Zoman
fonte
Parece que pode funcionar, alguém já usou? Como é o uso de memória?
Frozenskys
Ele tem a capacidade de adicionar uma marca d'água de texto e, se tiver sido formatado corretamente, pode funcionar.
Frozenskys