174 votes

Fusionner des fichiers PDF

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

En supposant que ce soit le cas, j'ai besoin d'aller un peu plus loin. J'espère pouvoir parcourir en boucle les dossiers d'un répertoire et répéter cette procédure.

Et je pousse peut-être le bouchon un peu loin, mais est-il possible d'exclure une page contenue dans les PDF (la génération de mon rapport crée toujours une page blanche supplémentaire).

287voto

Paul Rooney Points 12166

Vous pouvez utiliser PyPdf2 s PdfMerger classe.

Concaténation de fichiers

Vous pouvez simplement concaténer en utilisant l'option append mé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 passer des handles de fichiers au lieu de chemins de fichiers si vous le souhaitez.

Fusion de fichiers

Si vous voulez un contrôle plus fin de la fusion, il existe une merge de la méthode 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. Le site append peut être considérée comme une merge 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.

Gammes de pages

Si vous souhaitez contrôler les pages qui sont ajoutées à partir d'un fichier particulier, vous pouvez utiliser la commande pages argument de mot-clé de append y merge en passant un tuple de la forme (start, stop[, step]) (comme l'ordinaire range fonction).

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 un intervalle non valide, vous obtiendrez un IndexError .

Nota: également que, pour éviter que des dossiers ne restent ouverts, la PdfFileMerger 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 voulu. Il est dommage que PdfFileMerger n'est pas implémenté en tant que gestionnaire de contexte, nous pouvons donc utiliser la fonction with pour éviter de passer à côté d'un problème explicite et obtenir une protection facile contre les exceptions.

Vous pouvez également consulter le pdfcat script fourni dans le cadre de pypdf2. Vous pouvez potentiellement éviter d'avoir à écrire du code.

Le github de PyPdf2 a également comprend un exemple de code démontrant la fusion.

PyMuPdf

Une autre bibliothèque qui vaut peut-être le coup d'œil est PyMuPdf qui semble être activement maintenu. La fusion est tout aussi simple

Depuis la ligne de commande :

python -m fitz join -o result.pdf file1.pdf file2.pdf file3.pdf

et du code

import fitz

result = fitz.open()

for pdf in ['file1.pdf', 'file2.pdf', 'file3.pdf']:
    with fitz.open(pdf) as mfile:
        result.insertPDF(mfile)

result.save("result.pdf")

Avec de nombreuses options, détaillées dans les projets wiki .

1 votes

Ce devrait être la réponse choisie.

1 votes

Tu m'as sauvé, merci.

143voto

Gilles Points 37537

Utilisez Pypdf ou son successeur PyPDF2 :

Une bibliothèque Pure-Python construite comme une boîte à outils PDF. Elle est capable de :

  • diviser les documents page par page,
  • fusionner des documents page par page,

(et bien plus encore)

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
        # https://stackoverflow.com/questions/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()
        output_stream.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)

21 votes

Et maintenant, pypi.python.org/pypi/PyPDF2 qui est le projet successeur de PyPDF

1 votes

Cela ne fonctionne pour moi qu'avec une ouverture en mode binaire (flux d'entrée et également flux de sortie). open(input_file), 'r+b' et au lieu de sys.stdout j'utilise output_stream = open('result.pdf', 'w+b') .

0 votes

@SimeonBorko Laissez tomber le + Il signifie "lire et écrire" et aucun fichier n'est à la fois lu et écrit. J'ai ajouté le support de sortie de Windows basé sur stackoverflow.com/questions/2374427/ .

30voto

Giovanni Gianni Points 6186

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

Mettez les fichiers pdf dans un répertoire. Lancez le programme. Vous obtenez un pdf avec tous les 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)

Comment puis-je faire le même code que ci-dessus aujourd'hui

from glob import glob
from PyPDF2 import PdfFileMerger

def pdf_merge():
    ''' Merges all the pdf files in current directory '''
    merger = PdfFileMerger()
    allpdfs = [a for a in glob("*.pdf")]
    [merger.append(pdf) for pdf in allpdfs]
    with open("Merged_pdfs.pdf", "wb") as new_file:
        merger.write(new_file)

if __name__ == "__main__":
    pdf_merge()

1 votes

J'ai utilisé ceci avec succès

13voto

Patrick Maupin Points 6009

El pdfrw bibliothèque peut le faire assez facilement, à condition que vous n'ayez pas besoin de préserver les signets et les annotations, et que vos PDF ne soient pas cryptés. cat.py est un exemple de concaténation script, et subset.py est un exemple de page de sous-ensemble script.

La partie pertinente de la concaténation script -- assume inputs est une liste de noms de fichiers d'entrée, et outfn est 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 constater, il serait assez facile d'omettre la dernière page, par exemple quelque chose du genre :

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

Disclaimer : Je suis le principal pdfrw auteur.

1 votes

C'est le plus stable.

1 votes

Cette bibliothèque mérite une plus grande réputation.

9voto

moose Points 4945

Est-il possible, en utilisant Python, de fusionner des fichiers PDF distincts ?

Sí.

L'exemple suivant fusionne tous les fichiers d'un dossier en 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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X