Mesclar arquivos PDF

126

É possível, usando Python, mesclar arquivos PDF separados?

Supondo que sim, preciso estender isso um pouco mais. Espero percorrer as pastas de um diretório e repetir este procedimento.

E posso estar abusando da sorte, mas é possível excluir uma página contida nos PDFs (minha geração de relatório sempre cria uma página em branco extra).

Btibert3
fonte

Respostas:

122

Use Pypdf ou seu sucessor PyPDF2 :

Uma biblioteca Pure-Python construída como um kit de ferramentas PDF. É capaz de:
* dividir documentos página por página,
* mesclar documentos página por página,

(e muito mais)

Aqui está um programa de amostra que funciona com as duas versões.

#!/usr/bin/env python
import sys
try:
    from PyPDF2 import PdfFileReader, PdfFileWriter
except ImportError:
    from pyPdf import PdfFileReader, PdfFileWriter

def pdf_cat(input_files, output_stream):
    input_streams = []
    try:
        # First open all the files, then produce the output file, and
        # finally close the input files. This is necessary because
        # the data isn't read from the input files until the write
        # operation. Thanks to
        # /programming/6773631/problem-with-closing-python-pypdf-writing-getting-a-valueerror-i-o-operation/6773733#6773733
        for input_file in input_files:
            input_streams.append(open(input_file, 'rb'))
        writer = PdfFileWriter()
        for reader in map(PdfFileReader, input_streams):
            for n in range(reader.getNumPages()):
                writer.addPage(reader.getPage(n))
        writer.write(output_stream)
    finally:
        for f in input_streams:
            f.close()

if __name__ == '__main__':
    if sys.platform == "win32":
        import os, msvcrt
        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
    pdf_cat(sys.argv[1:], sys.stdout)
Gilles 'SO- pare de ser mal'
fonte
19
E agora, pypi.python.org/pypi/PyPDF2 que é o projeto sucessor do PyPDF
David Fraser
Funciona para mim apenas com a abertura no modo binário (fluxos de entrada e também fluxo de saída). open(input_file), 'r+b', e em vez de sys.stdout eu uso output_stream = open('result.pdf', 'w+b').
Simeon Borko
@SimeonBorko Elimine o +, significa “ler e escrever” e nenhum dos arquivos é lido e escrito. Eu adicionei suporte de saída de suporte do Windows com base em stackoverflow.com/questions/2374427/… .
Gilles 'SO- pare de ser mal'
PyPDF2 / 3 não é estável, como posso mesclar arquivos pdf sem PyPDF2 / 3.
GoingMyWay
2
Tive que usar sys.stdout.bufferPython 3.6.8 (Linux)
Greyshack
197

Você pode usar a classe do PyPdf2PdfMerger .

Concatenação de arquivo

Você pode simplesmente concatenar arquivos usando o appendmétodo.

from PyPDF2 import PdfFileMerger

pdfs = ['file1.pdf', 'file2.pdf', 'file3.pdf', 'file4.pdf']

merger = PdfFileMerger()

for pdf in pdfs:
    merger.append(pdf)

merger.write("result.pdf")
merger.close()

Você pode passar identificadores de arquivo em vez de caminhos de arquivo, se desejar.

Mesclagem de arquivos

Se você quiser um controle mais refinado da mesclagem, existe um mergemétodo do PdfMerger, que permite especificar um ponto de inserção no arquivo de saída, o que significa que você pode inserir as páginas em qualquer lugar do arquivo. O appendmétodo pode ser considerado como mergeonde o ponto de inserção é o final do arquivo.

por exemplo

merger.merge(2, pdf)

Aqui, inserimos todo o pdf na saída, mas na página 2.

Intervalos de páginas

Se você deseja controlar quais páginas são anexadas de um arquivo específico, você pode usar o pagesargumento de palavra - chave de appendemerge , passando uma tupla na forma (start, stop[, step])(como a rangefunção regular ).

por exemplo

merger.append(pdf, pages=(0, 3))    # first 3 pages
merger.append(pdf, pages=(0, 6, 2)) # pages 1,3, 5

Se você especificar um intervalo inválido, obterá um IndexError .

Nota: também para evitar que os arquivos PdfFileMergerfiquem abertos, o método s close deve ser chamado quando o arquivo mesclado for gravado. Isso garante que todos os arquivos sejam fechados (entrada e saída) em tempo hábil. É uma pena que PdfFileMergernão seja implementado como um gerenciador de contexto, então podemos usar a withpalavra - chave, evitar a chamada fechada explícita e obter alguma segurança de exceção fácil.

Você também pode querer dar uma olhada no pdfcatscript fornecido como parte do pypdf2. Você pode potencialmente evitar a necessidade de escrever código completamente.

O github PyPdf2 também inclui alguns exemplos de código que demonstram a fusão.

Paul Rooney
fonte
14

Mesclar todos os arquivos PDF que estão presentes em um diretório

Coloque os arquivos PDF em um diretório. Lance o programa. Você recebe um pdf com todos os pdfs mesclados.

import os
from PyPDF2 import PdfFileMerger

x = [a for a in os.listdir() if a.endswith(".pdf")]

merger = PdfFileMerger()

for pdf in x:
    merger.append(open(pdf, 'rb'))

with open("result.pdf", "wb") as fout:
    merger.write(fout)
Giovanni G. PY
fonte
8

A pdfrwbiblioteca pode fazer isso facilmente, supondo que você não precise preservar marcadores e anotações, e seus PDFs não estão criptografados. cat.pyé um exemplo de script de concatenação esubset.py um script de subconjunto de página de exemplo.

A parte relevante do script de concatenação - assume que inputsé uma lista de nomes de arquivos de entrada e outfné um nome de arquivo de saída:

from pdfrw import PdfReader, PdfWriter

writer = PdfWriter()
for inpfn in inputs:
    writer.addpages(PdfReader(inpfn).pages)
writer.write(outfn)

Como você pode ver, seria muito fácil deixar de fora a última página, por exemplo, algo como:

    writer.addpages(PdfReader(inpfn).pages[:-1])

Isenção de responsabilidade: eu sou o pdfrwautor principal .

Patrick Maupin
fonte
1
Este é o mais estável.
GoingMyWay
1
Esta biblioteca merece mais reputação.
GoingMyWay
6

É possível, usando Python, mesclar arquivos PDF separados?

Sim.

O exemplo a seguir mescla todos os arquivos em uma pasta em um único novo arquivo PDF:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from argparse import ArgumentParser
from glob import glob
from pyPdf import PdfFileReader, PdfFileWriter
import os

def merge(path, output_filename):
    output = PdfFileWriter()

    for pdffile in glob(path + os.sep + '*.pdf'):
        if pdffile == output_filename:
            continue
        print("Parse '%s'" % pdffile)
        document = PdfFileReader(open(pdffile, 'rb'))
        for i in range(document.getNumPages()):
            output.addPage(document.getPage(i))

    print("Start writing '%s'" % output_filename)
    with open(output_filename, "wb") as f:
        output.write(f)

if __name__ == "__main__":
    parser = ArgumentParser()

    # Add more options if you like
    parser.add_argument("-o", "--output",
                        dest="output_filename",
                        default="merged.pdf",
                        help="write merged PDF to FILE",
                        metavar="FILE")
    parser.add_argument("-p", "--path",
                        dest="path",
                        default=".",
                        help="path of source PDF files")

    args = parser.parse_args()
    merge(args.path, args.output_filename)
Martin Thoma
fonte
3
from PyPDF2 import PdfFileMerger
import webbrowser
import os
dir_path = os.path.dirname(os.path.realpath(__file__))

def list_files(directory, extension):
    return (f for f in os.listdir(directory) if f.endswith('.' + extension))

pdfs = list_files(dir_path, "pdf")

merger = PdfFileMerger()

for pdf in pdfs:
    merger.append(open(pdf, 'rb'))

with open('result.pdf', 'wb') as fout:
    merger.write(fout)

webbrowser.open_new('file://'+ dir_path + '/result.pdf')

Git Repo: https://github.com/mahaguru24/Python_Merge_PDF.git

guruprasad mulay
fonte
2

aqui, http://pieceofpy.com/2009/03/05/concatenating-pdf-with-python/ , oferece uma solução.

similarmente:

from pyPdf import PdfFileWriter, PdfFileReader

def append_pdf(input,output):
    [output.addPage(input.getPage(page_num)) for page_num in range(input.numPages)]

output = PdfFileWriter()

append_pdf(PdfFileReader(file("C:\\sample.pdf","rb")),output)
append_pdf(PdfFileReader(file("c:\\sample1.pdf","rb")),output)
append_pdf(PdfFileReader(file("c:\\sample2.pdf","rb")),output)
append_pdf(PdfFileReader(file("c:\\sample3.pdf","rb")),output)

    output.write(file("c:\\combined.pdf","wb"))
Mark K
fonte
0

Uma ligeira variação usando um dicionário para maior flexibilidade (por exemplo, classificação, desduplicação):

import os
from PyPDF2 import PdfFileMerger
# use dict to sort by filepath or filename
file_dict = {}
for subdir, dirs, files in os.walk("<dir>"):
    for file in files:
        filepath = subdir + os.sep + file
        # you can have multiple endswith
        if filepath.endswith((".pdf", ".PDF")):
            file_dict[file] = filepath
# use strict = False to ignore PdfReadError: Illegal character error
merger = PdfFileMerger(strict=False)

for k, v in file_dict.items():
    print(k, v)
    merger.append(v)

merger.write("combined_result.pdf")
Ogaga Uzoh
fonte
0

Eu usei o pdf unite no terminal linux aproveitando o subprocesso (assume que existam one.pdf e two.pdf no diretório) e o objetivo é mesclá-los em three.pdf

 import subprocess
 subprocess.call(['pdfunite one.pdf two.pdf three.pdf'],shell=True)
user8291021
fonte