Unisci file PDF


126

È possibile, utilizzando Python, unire file PDF separati?

Supponendo che sia così, ho bisogno di estenderlo ancora un po '. Spero di scorrere le cartelle in una directory e ripetere questa procedura.

E potrei sfidare la mia fortuna, ma è possibile escludere una pagina contenuta nei PDF (la mia generazione di report crea sempre una pagina vuota extra).

Risposte:


122

Usa Pypdf o il suo successore PyPDF2 :

Una libreria Pure-Python costruita come un toolkit PDF. È in grado di:
* dividere documenti pagina per pagina,
* unire documenti pagina per pagina,

(e altro ancora)

Ecco un programma di esempio che funziona con entrambe le versioni.

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

19
E ora, pypi.python.org/pypi/PyPDF2 che è il progetto successore di PyPDF
David Fraser

Per me funziona solo con l'apertura in modalità binaria (flussi di input e anche flusso di output). open(input_file), 'r+b'e invece di sys.stdout uso output_stream = open('result.pdf', 'w+b').
Simeon Borko

@SimeonBorko Rilascia il +, significa "leggi e scrivi" e nessuno dei due file viene letto e scritto. Ho aggiunto il supporto dell'output del supporto di Windows basato su stackoverflow.com/questions/2374427/… .
Gilles "SO- smettila di essere cattivo"

PyPDF2 / 3 non è stabile, come posso unire file pdf senza PyPDF2 / 3.
GoingMyWay

2
Ho dovuto usare sys.stdout.bufferPython 3.6.8 (Linux)
Greyshack

197

Puoi usare la classe di PyPdf2PdfMerger .

Concatenazione di file

Puoi semplicemente concatenare i file usando il appendmetodo.

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

Puoi passare handle di file invece di percorsi di file se lo desideri.

Unione di file

Se si desidera un controllo più dettagliato dell'unione, è disponibile un mergemetodo di PdfMerger, che consente di specificare un punto di inserimento nel file di output, il che significa che è possibile inserire le pagine ovunque nel file. Il appendmetodo può essere pensato come un punto in mergecui il punto di inserimento è la fine del file.

per esempio

merger.merge(2, pdf)

Qui inseriamo l'intero pdf nell'output ma a pagina 2.

Intervalli di pagine

Se desideri controllare quali pagine sono aggiunte da un particolare file, puoi usare l' pagesargomento della parola chiave appende merge, passando una tupla nel modulo (start, stop[, step])(come la rangefunzione normale ).

per esempio

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

Se specifichi un intervallo non valido, otterrai un IndexError.

Nota: inoltre, per evitare che i file vengano lasciati aperti, il PdfFileMergermetodo di chiusura s dovrebbe essere chiamato quando il file unito è stato scritto. Ciò garantisce che tutti i file vengano chiusi (input e output) in modo tempestivo. È un peccato che PdfFileMergernon sia implementato come gestore di contesto, quindi possiamo usare la withparola chiave, evitare la chiamata di chiusura esplicita e ottenere un po 'di sicurezza dalle eccezioni.

Potresti anche voler guardare lo pdfcatscript fornito come parte di pypdf2. È possibile evitare potenzialmente la necessità di scrivere del codice del tutto.

Il GitHub PyPdf2 include anche alcuni esempi di codice che dimostrano l'unione.


14

Unisci tutti i file pdf presenti in una directory

Metti i file pdf in una directory. Avvia il programma. Ottieni un pdf con tutti i pdf uniti.

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)

8

La pdfrwlibreria può farlo abbastanza facilmente, supponendo che non sia necessario conservare segnalibri e annotazioni e che i PDF non siano crittografati. cat.pyè uno script di concatenazione di esempio ed subset.pyè uno script di sottoinsiemi di pagine di esempio.

La parte rilevante dello script di concatenazione - presuppone che inputssia un elenco di nomi di file di input ed outfnè un nome di file di output:

from pdfrw import PdfReader, PdfWriter

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

Come puoi vedere da questo, sarebbe abbastanza facile tralasciare l'ultima pagina, ad esempio qualcosa come:

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

Disclaimer: io sono l' pdfrwautore principale .


1
Questo è il più stabile.
GoingMyWay

1
Questa libreria merita più reputazione.
GoingMyWay

6

È possibile, utilizzando Python, unire file PDF separati?

Sì.

L'esempio seguente unisce tutti i file in una cartella in un unico nuovo file 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)

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

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


2

qui, http://pieceofpy.com/2009/03/05/concatenating-pdf-with-python/ , fornisce una soluzione.

simile:

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

0

Una leggera variazione utilizzando un dizionario per una maggiore flessibilità (ad es. Ordinamento, deduplicazione):

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

0

Ho usato pdf unite sul terminale linux sfruttando il sottoprocesso (presume che uno.pdf e due.pdf esistano nella directory) e l'obiettivo è unirli a tre.pdf

 import subprocess
 subprocess.call(['pdfunite one.pdf two.pdf three.pdf'],shell=True)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.