Fusionner des fichiers PDF

126

Est-il possible, en utilisant Python, de fusionner des fichiers PDF séparés?

En supposant que oui, je dois étendre ceci un peu plus loin. J'espère parcourir les dossiers d'un répertoire et répéter cette procédure.

Et je pousse peut-être ma chance, mais est-il possible d'exclure une page qui est contenue dans des PDF (ma génération de rapport crée toujours une page vierge supplémentaire).

Btibert3
la source

Réponses:

122

Utilisez Pypdf ou son successeur PyPDF2 :

Une bibliothèque Pure-Python construite sous forme de boîte à outils PDF. Il est capable de:
* fractionner les documents page par page,
* fusionner les documents page par page,

(et beaucoup plus)

Voici un exemple de programme qui fonctionne avec les deux versions.

#!/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- arrête d'être méchant'
la source
19
Et maintenant, pypi.python.org/pypi/PyPDF2 qui est le projet successeur de PyPDF
David Fraser
Fonctionne pour moi uniquement avec une ouverture en mode binaire (flux d'entrée et flux de sortie). open(input_file), 'r+b', et au lieu de sys.stdout, j'utilise output_stream = open('result.pdf', 'w+b').
Simeon Borko
@SimeonBorko Supprimez le +, cela signifie «lire et écrire» et aucun des fichiers n'est à la fois lu et écrit. J'ai ajouté la prise en charge de la sortie de support Windows basée sur stackoverflow.com/questions/2374427/… .
Gilles 'SO- arrête d'être mauvais'
PyPDF2 / 3 n'est pas stable, comment puis-je fusionner des fichiers pdf sans PyPDF2 / 3.
GoingMyWay
2
J'ai dû utiliser sys.stdout.bufferPython 3.6.8 (Linux)
Greyshack
197

Vous pouvez utiliser PyPdf2 de PdfMergerclasse.

Concaténation de fichiers

Vous pouvez simplement concaténer des fichiers en utilisant la appendméthode.

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

Vous pouvez transmettre des descripteurs de fichiers à la place des chemins de fichiers si vous le souhaitez.

Fusion de fichiers

Si vous souhaitez un contrôle plus fin de la fusion, il existe une mergeméthode du PdfMerger, qui vous permet de spécifier un point d'insertion dans le fichier de sortie, ce qui signifie que vous pouvez insérer les pages n'importe où dans le fichier. La appendméthode peut être considérée comme un mergeendroit où le point d'insertion est la fin du fichier.

par exemple

merger.merge(2, pdf)

Ici, nous insérons le pdf entier dans la sortie mais à la page 2.

Plages de pages

Si vous souhaitez contrôler quelles pages sont ajoutées à partir d'un fichier particulier, vous pouvez utiliser l' pagesargument mot - clé de appendet merge, en passant un tuple sous la forme (start, stop[, step])(comme la rangefonction régulière ).

par exemple

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

Si vous spécifiez une plage non valide, vous obtiendrez un fichier IndexError.

Remarque: également que pour éviter de laisser les fichiers ouverts, la PdfFileMergerméthode close doit être appelée lorsque le fichier fusionné a été écrit. Cela garantit que tous les fichiers sont fermés (entrée et sortie) en temps opportun. C'est dommage que ce PdfFileMergerne soit pas implémenté en tant que gestionnaire de contexte, nous pouvons donc utiliser le withmot - clé, éviter l'appel de fermeture explicite et obtenir une sécurité d'exception facile.

Vous pouvez également consulter le pdfcatscript fourni dans le cadre de pypdf2. Vous pouvez potentiellement éviter d'avoir à écrire du code complètement.

Le github PyPdf2 comprend également des exemples de code démontrant la fusion.

Paul Rooney
la source
14

Fusionner tous les fichiers pdf présents dans un répertoire

Mettez les fichiers pdf dans un répertoire. Lancer le programme. Vous obtenez un pdf avec tous les fichiers PDF fusionnés.

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
la source
8

La pdfrwbibliothèque peut le faire assez facilement, en supposant que vous n'ayez pas besoin de conserver les signets et les annotations, et que vos PDF ne sont pas cryptés. cat.pyest un exemple de script de concaténation et subset.pyun exemple de script de sous-définition de page.

La partie pertinente du script de concaténation - suppose qu'il inputss'agit d'une liste de noms de fichiers d'entrée et outfnest un nom de fichier de sortie:

from pdfrw import PdfReader, PdfWriter

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

Comme vous pouvez le voir, il serait assez facile de laisser de côté la dernière page, par exemple quelque chose comme:

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

Avertissement: Je suis l' pdfrwauteur principal .

Patrick Maupin
la source
1
C'est le plus stable.
GoingMyWay
1
Cette bibliothèque mérite plus de réputation.
GoingMyWay
6

Est-il possible, en utilisant Python, de fusionner des fichiers PDF séparés?

Oui.

L'exemple suivant fusionne tous les fichiers d'un dossier dans un seul nouveau fichier 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
la source
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

gourouprasad mulay
la source
2

ici, http://pieceofpy.com/2009/03/05/concatenating-pdf-with-python/ , donne une solution.

De même:

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
la source
0

Une légère variation en utilisant un dictionnaire pour une plus grande flexibilité (ex: tri, dédup):

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
la source
0

J'ai utilisé pdf unite sur le terminal linux en tirant parti du sous-processus (suppose que one.pdf et two.pdf existent sur le répertoire) et le but est de les fusionner en three.pdf

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