PDF-Dateien zusammenführen

126

Ist es mit Python möglich, separate PDF-Dateien zusammenzuführen?

Vorausgesetzt, ich muss dies etwas weiter ausbauen. Ich hoffe, Ordner in einem Verzeichnis zu durchlaufen und diesen Vorgang zu wiederholen.

Ich werde vielleicht mein Glück versuchen, aber es ist möglich, eine Seite auszuschließen, die in den PDFs enthalten ist (meine Berichtserstellung erstellt immer eine zusätzliche leere Seite).

Btibert3
quelle

Antworten:

122

Verwenden Sie Pypdf oder dessen Nachfolger PyPDF2 :

Eine Pure-Python-Bibliothek, die als PDF-Toolkit erstellt wurde. Es ist in der Lage:
* Dokumente Seite für Seite aufzuteilen,
* Dokumente Seite für Seite zusammenzuführen, *

(und vieles mehr)

Hier ist ein Beispielprogramm, das mit beiden Versionen funktioniert.

#!/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 - hör auf böse zu sein'
quelle
19
Und jetzt pypi.python.org/pypi/PyPDF2 , das Nachfolgeprojekt von PyPDF
David Fraser
Funktioniert bei mir nur beim Öffnen im Binärmodus (Eingangsströme und auch Ausgangsströme). open(input_file), 'r+b'und anstelle von sys.stdout verwende ich output_stream = open('result.pdf', 'w+b').
Simeon Borko
@SimeonBorko Löschen Sie das +, es bedeutet "Lesen und Schreiben" und keine Datei wird sowohl gelesen als auch geschrieben. Ich habe die Ausgabeunterstützung für Windows-Unterstützung basierend auf stackoverflow.com/questions/2374427/… hinzugefügt .
Gilles 'SO - hör auf böse zu sein'
PyPDF2 / 3 ist nicht stabil. Wie kann ich PDF-Dateien ohne PyPDF2 / 3 zusammenführen?
GoingMyWay
2
Ich musste sys.stdout.bufferPython 3.6.8 (Linux) verwenden
Greyshack
196

Sie können mit PyPdf2 s PdfMergerKlasse.

Dateikettung

Mit der Methode können Sie Dateien einfach verkettenappend .

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

Sie können stattdessen Dateihandles anstelle von Dateipfaden übergeben, wenn Sie möchten.

Zusammenführen von Dateien

Wenn Sie eine genauere Steuerung des Zusammenführens wünschen, gibt es eine mergeMethode von PdfMerger, mit der Sie eine Einfügemarke in der Ausgabedatei angeben können, dh Sie können die Seiten an einer beliebigen Stelle in der Datei einfügen. Die appendMethode kann als eine Methode angesehen werden, mergebei der die Einfügemarke das Ende der Datei ist.

z.B

merger.merge(2, pdf)

Hier fügen wir das gesamte PDF in die Ausgabe ein, jedoch auf Seite 2.

Seitenbereiche

Wenn Sie steuern möchten, welche Seiten aus einer bestimmten Datei angehängt werden, können Sie das pagesSchlüsselwortargument von appendund verwenden mergeund ein Tupel im Formular übergeben (start, stop[, step])(wie die reguläre rangeFunktion).

z.B

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

Wenn Sie einen ungültigen Bereich angeben, erhalten Sie einen IndexError.

Hinweis: Um zu vermeiden, dass Dateien geöffnet bleiben, sollte die PdfFileMergerMethode s close aufgerufen werden, wenn die zusammengeführte Datei geschrieben wurde. Dies stellt sicher, dass alle Dateien rechtzeitig geschlossen (Eingabe und Ausgabe) werden. Es ist eine Schande, dass dies PdfFileMergernicht als Kontextmanager implementiert ist, sodass wir das withSchlüsselwort verwenden, den expliziten Abschlussaufruf vermeiden und eine einfache Ausnahmesicherheit erhalten können.

Vielleicht möchten Sie sich auch das pdfcatSkript ansehen, das als Teil von pypdf2 bereitgestellt wird. Sie können möglicherweise vermeiden, dass Code vollständig geschrieben werden muss.

Der PyPdf2-Github enthält auch einen Beispielcode, der das Zusammenführen demonstriert.

Paul Rooney
quelle
14

Führen Sie alle PDF-Dateien zusammen, die in einem Verzeichnis vorhanden sind

Legen Sie die PDF-Dateien in ein Verzeichnis. Starten Sie das Programm. Sie erhalten ein PDF mit allen zusammengeführten PDFs.

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
quelle
8

Die pdfrwBibliothek kann dies ganz einfach tun, vorausgesetzt, Sie müssen keine Lesezeichen und Anmerkungen beibehalten und Ihre PDFs sind nicht verschlüsselt. cat.pyist ein Beispiel für ein Verkettungsskript und subset.pyein Beispiel für ein Teilmengen-Skript.

Der relevante Teil des Verkettungsskripts - setzt voraus, dass inputses sich um eine Liste von Eingabedateinamen und outfneinen Ausgabedateinamen handelt:

from pdfrw import PdfReader, PdfWriter

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

Wie Sie daraus sehen können, wäre es ziemlich einfach, die letzte Seite wegzulassen, z. B.:

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

Haftungsausschluss: Ich bin der pdfrwHauptautor.

Patrick Maupin
quelle
1
Dies ist die stabilste.
GoingMyWay
1
Diese Bibliothek verdient mehr Ansehen.
GoingMyWay
6

Ist es mit Python möglich, separate PDF-Dateien zusammenzuführen?

Ja.

Im folgenden Beispiel werden alle Dateien in einem Ordner zu einer einzigen neuen PDF-Datei zusammengeführt:

#!/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
quelle
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
quelle
2

Hier gibt http://pieceofpy.com/2009/03/05/concatenating-pdf-with-python/ eine Lösung.

ähnlich:

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.
quelle
0

Eine geringfügige Abweichung bei Verwendung eines Wörterbuchs für mehr Flexibilität (z. B. Sortieren, Dedupieren):

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
quelle
0

Ich habe pdf unite auf dem Linux-Terminal verwendet, indem ich den Unterprozess genutzt habe (vorausgesetzt, im Verzeichnis sind one.pdf und two.pdf vorhanden), und das Ziel ist, sie zu three.pdf zusammenzuführen

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