Объединить файлы PDF
Возможно ли с помощью Python объединить отдельные PDF файлы?
Предполагая, что так, я должен расширить это немного дальше. Я надеюсь перебрать папки в каталоге и повторить эту процедуру.
И я могу испытывать удачу, но возможно ли исключить страницу, содержащуюся в PDF файлах (при создании моего отчета всегда создается дополнительная пустая страница).
Ответы
Ответ 1
Используйте 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
# 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()
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)
Ответ 2
Вы можете использовать PyPdf2PdfMerger
класс.
Конкатенация файлов
Вы можете просто объединить файлы, используя метод 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
.
Примечание: также чтобы во время записи объединенного файла вызывать метод close PdfFileMerger
, чтобы не оставлять файлы открытыми. Это гарантирует, что все файлы будут закрыты (вход и выход) своевременно. Жаль, что PdfFileMerger
не реализован в качестве менеджера контекста, поэтому мы можем использовать ключевое слово with
, избегать явного вызова close и получить некоторую легкую безопасность исключений.
Возможно, вы также захотите взглянуть на скрипт pdfcat
, который входит в состав pypdf2. Вы можете избежать необходимости писать код целиком.
Github PyPdf2 также включает в себя пример кода, демонстрирующего слияние.
Ответ 3
Вам нужно использовать python? если вам просто нужно объединить ваши pdf файлы, я бы посмотрел на pdftk
Ответ 4
Возможно ли, используя 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)
Ответ 5
Объединить все 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)
Ответ 6
Библиотека 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
.
Ответ 7
здесь 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"))
Ответ 8
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
Ответ 9
Небольшое изменение с использованием словаря для большей гибкости (например, сортировка, дедупликация):
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")
Ответ 10
Также возможно использовать Aspose.PDF Cloud SDK для Python. Вот быстрый пример:
#upload PDF files to aspose cloud storage
storageApi.PutCreate(file1, null, null, path1)
storageApi.PutCreate(file2, null, null, path2)
#merge files into one PDF
pdfApi.PutMergeDocuments(name, null, null, mergeDocumentsBody)
#download merged PDF from storage server
storageApi.GetDownload(name)
Самым большим преимуществом является то, что API предоставляет множество других возможностей для управления вашими PDF файлами. Вы можете изменять, конвертировать, шифровать файлы; обрабатывать страницы, текст, формы и другие элементы.
Примечание: я работаю в качестве разработчика Evangelist в Aspose.