Объединить файлы PDF

126

Можно ли с помощью Python объединить отдельные файлы PDF?

Предполагая, что это так, мне нужно расширить это немного дальше. Я надеюсь перебрать папки в каталоге и повторить эту процедуру.

И я, возможно, испытываю удачу, но можно ли исключить страницу, содержащуюся в PDF-файлах (при создании моего отчета всегда создается дополнительная пустая страница).

Btibert3
источник

Ответы:

122

Используйте Pypdf или его преемника PyPDF2 :

Библиотека Pure-Python, созданная как набор инструментов PDF. Он способен:
* разбивать документы по страницам,
* объединять документы по страницам,

(и многое другое)

Вот пример программы, которая работает с обеими версиями.

#!/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
А теперь pypi.python.org/pypi/PyPDF2, который является преемником PyPDF
Дэвид Фрейзер
У меня работает только с открытием в двоичном режиме (входные потоки, а также выходной поток). open(input_file), 'r+b', а вместо sys.stdout использую output_stream = open('result.pdf', 'w+b').
Симеон Борко
@SimeonBorko Отбросьте +, это означает «чтение и запись», и ни один файл не читается и не записывается одновременно. Я добавил поддержку вывода поддержки Windows на основе stackoverflow.com/questions/2374427/… .
Жиль 'SO- перестань быть злом'
PyPDF2 / 3 нестабилен, как я могу объединить файлы PDF без PyPDF2 / 3.
GoingMyWay
2
Мне пришлось использовать sys.stdout.bufferPython 3.6.8 (Linux)
Greyshack
198

Вы можете использовать PyPdf2 сек PdfMergerкласс.

Объединение файлов

Вы можете просто объединить файлы с помощью appendметода.

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

Вы можете передавать дескрипторы файлов вместо путей к файлам, если хотите.

Слияние файлов

Если вам нужен более детальный контроль слияния, существует mergeметод PdfMerger, который позволяет вам указать точку вставки в выходном файле, что означает, что вы можете вставлять страницы в любом месте файла. Этот appendметод можно представить как mergeточку вставки в конце файла.

например

merger.merge(2, pdf)

Здесь мы вставляем в выходной файл весь PDF-файл, но на странице 2.

Диапазоны страниц

Если вы хотите контролировать, какие страницы добавляются из определенного файла, вы можете использовать pagesаргумент ключевого слова appendи merge, передавая кортеж в форме (start, stop[, step])(как обычная rangeфункция).

например

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

Если вы укажете недопустимый диапазон, вы получите расширение IndexError.

Примечание: также, чтобы файлы не оставались открытыми, метод PdfFileMergers close следует вызывать после записи объединенного файла. Это гарантирует своевременное закрытие всех файлов (ввод и вывод). Жаль, что PdfFileMergerон не реализован в качестве диспетчера контекста, поэтому мы можем использовать withключевое слово, избежать явного вызова закрытия и получить легкую защиту от исключений.

Вы также можете посмотреть pdfcatсценарий, предоставленный как часть pypdf2. Потенциально вы можете вообще избежать необходимости писать код.

В github PyPdf2 также есть пример кода, демонстрирующий слияние.

Пол Руни
источник
15

Объединить все файлы pdf, которые присутствуют в каталоге

Поместите файлы pdf в каталог. Запустить программу. Вы получаете один PDF-файл со всеми объединенными PDF-файлами.

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

pdfrwБиблиотека может сделать это довольно легко, при условии , что вам не нужно , чтобы сохранить закладки и аннотации, и ваши PDF - файлы не шифруются. cat.pyпример сценария конкатенации, иsubset.py пример сценария разбиения страницы.

Соответствующая часть сценария конкатенации - предполагает, inputsчто это список имен входных файлов и outfnимя выходного файла:

from pdfrw import PdfReader, PdfWriter

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

Как видно из этого, было бы довольно легко пропустить последнюю страницу, например, что-то вроде:

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

Отказ от ответственности: я являюсь основным pdfrwавтором.

Патрик Мопен
источник
1
Это самый стабильный.
GoingMyWay
1
Эта библиотека заслуживает большей репутации.
GoingMyWay
6

Можно ли с помощью Python объединить отдельные файлы PDF?

Да.

В следующем примере все файлы в одной папке объединяются в один новый 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')

Репозиторий Git: https://github.com/mahaguru24/Python_Merge_PDF.git

гурупрасад мулай
источник
2

здесь http://pieceofpy.com/2009/03/05/concatenating-pdf-with-python/ дает решение.

так же:

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

Небольшая вариация с использованием словаря для большей гибкости (например, сортировка, дедупликация):

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

Я использовал pdf unite в терминале Linux, используя подпроцесс (предполагается, что в каталоге существуют one.pdf и two.pdf), и цель состоит в том, чтобы объединить их с three.pdf

 import subprocess
 subprocess.call(['pdfunite one.pdf two.pdf three.pdf'],shell=True)
user8291021
источник