Об'єднайте PDF-файли


126

Чи можливо за допомогою Python об'єднати окремі файли PDF?

Припускаючи це, мені потрібно продовжити це трохи далі. Я сподіваюся прокрутити папки в каталозі та повторити цю процедуру.

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

Відповіді:


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
David Fraser

Для мене працює лише з відкриттям у двійковому режимі (вхідні потоки, а також вихідний потік). open(input_file), 'r+b', а замість sys.stdout я використовую output_stream = open('result.pdf', 'w+b').
Симеон Борко

@SimeonBorko Опустіть +, це означає "читати і писати", і жоден файл не читається і не записується. Я додав підтримку виходу Windows для підтримки на основі stackoverflow.com/questions/2374427/… .
Жил "ТАК - перестань бути злим"

PyPDF2 / 3 не є стабільним, як я можу об'єднати PDF-файли без PyPDF2 / 3.
GoingMyWay

2
Мені довелося користуватися sys.stdout.bufferPython 3.6.8 (Linux)
Greyshack,

197

Ви можете використовувати клас PyPdf2 s 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.

Зауважте: також, щоб уникнути залишення файлів відкритими, PdfFileMergerметод s закриття слід викликати, коли записаний файл об'єднаний. Це забезпечує своєчасне закриття всіх файлів (введення та виведення). Прикро, що PdfFileMergerне реалізується як менеджер контексту, тому ми можемо використовувати withключове слово, уникати явного закриття дзвінка та отримувати легку безпеку винятків.

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

Github PyPdf2 також містить деякий приклад коду, що демонструє злиття.


14

Об’єднайте всі файли pdf, які є у режимі

Покладіть файли pdf у dir. Запустіть програму. Ви отримуєте один pdf зі всіма об’єднаними файлами 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)

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 Repo: 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 об'єднатись на терміналі linux, використовуючи підпроцес (передбачається, що один.pdf та two.pdf існують у каталозі), а мета - об'єднати їх у три.pdf

 import subprocess
 subprocess.call(['pdfunite one.pdf two.pdf three.pdf'],shell=True)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.