Hợp nhất các tệp PDF


126

Có thể sử dụng Python để hợp nhất các tệp PDF riêng biệt không?

Giả sử như vậy, tôi cần mở rộng điều này thêm một chút. Tôi hy vọng lặp lại các thư mục trong một thư mục và lặp lại quy trình này.

Và tôi có thể đang thúc đẩy vận may của mình, nhưng liệu có thể loại trừ một trang có trong các tệp PDF không (tạo báo cáo của tôi luôn tạo thêm một trang trống).

Câu trả lời:


122

Sử dụng Pypdf hoặc PyPDF2 kế nhiệm của nó :

Thư viện Pure-Python được xây dựng dưới dạng bộ công cụ PDF. Nó có khả năng:
* tách tài liệu từng trang,
* hợp nhất tài liệu từng trang,

(và nhiều hơn nữa)

Đây là một chương trình mẫu hoạt động với cả hai phiên bản.

#!/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
Và bây giờ, pypi.python.org/pypi/PyPDF2 , là dự án kế thừa cho PyPDF
David Fraser

Chỉ hoạt động với tôi khi mở ở chế độ nhị phân (luồng đầu vào và cả luồng đầu ra). open(input_file), 'r+b', và thay vì sys.stdout tôi sử dụng output_stream = open('result.pdf', 'w+b').
Simeon Borko

@SimeonBorko Bỏ xuống +, nó có nghĩa là “đọc và ghi” và cả hai tệp đều không được đọc và ghi. Tôi đã thêm hỗ trợ đầu ra hỗ trợ Windows dựa trên stackoverflow.com/questions/2374427/… .
Gilles 'SO- đừng ác nữa'

PyPDF2 / 3 không ổn định, làm thế nào tôi có thể hợp nhất các tệp pdf mà không có PyPDF2 / 3.
GoingMyWay

2
Tôi đã phải sử dụng sys.stdout.buffersử dụng Python 3.6.8 (Linux)
Greyshack

197

Bạn có thể sử dụng lớp PyPdf2 s PdfMerger.

Kết nối tệp

Bạn có thể chỉ cần nối các tệp bằng cách sử dụng appendphương pháp này.

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

Bạn có thể chuyển các trình xử lý tệp thay vì đường dẫn tệp nếu muốn.

Hợp nhất tệp

Nếu bạn muốn kiểm soát chi tiết hơn việc hợp nhất, có một mergephương pháp PdfMergercho phép bạn chỉ định điểm chèn trong tệp đầu ra, nghĩa là bạn có thể chèn các trang vào bất kỳ đâu trong tệp. Các appendphương pháp có thể được coi như một mergenơi điểm chèn là kết thúc của tập tin.

ví dụ

merger.merge(2, pdf)

Ở đây chúng tôi chèn toàn bộ pdf vào đầu ra nhưng ở trang 2.

Phạm vi trang

Nếu bạn muốn kiểm soát những trang nào được nối từ một tệp cụ thể, bạn có thể sử dụng pagesđối số từ khóa của appendmerge, chuyển một bộ giá trị trong biểu mẫu (start, stop[, step])(như rangehàm thông thường ).

ví dụ

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

Nếu bạn chỉ định một phạm vi không hợp lệ, bạn sẽ nhận được IndexError.

Lưu ý: cũng để tránh các tệp bị bỏ ngỏ, PdfFileMergerphương thức s close nên được gọi khi tệp đã hợp nhất đã được ghi. Điều này đảm bảo tất cả các tệp được đóng (đầu vào và đầu ra) một cách kịp thời. Thật tiếc khi PdfFileMergernó không được triển khai như một trình quản lý ngữ cảnh, vì vậy chúng tôi có thể sử dụng withtừ khóa, tránh lệnh gọi gần rõ ràng và nhận được một số ngoại lệ an toàn dễ dàng.

Bạn cũng có thể muốn nhìn vào pdfcat tập lệnh được cung cấp như một phần của pypdf2. Bạn có thể tránh hoàn toàn việc phải viết mã.

PyPdf2 github cũng bao gồm một số mã ví dụ minh họa việc hợp nhất.


14

Hợp nhất tất cả các tệp pdf có trong một dir

Đặt các tệp pdf trong một dir. Khởi động chương trình. Bạn nhận được một pdf với tất cả các pdf được hợp nhất.

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

Các pdfrwthư viện có thể làm được điều này khá dễ dàng, giả sử bạn không cần phải giữ gìn dấu trang và chú thích, và PDF của bạn không được mã hóa. cat.pylà một tập lệnh nối ví dụ vàsubset.py là một tập lệnh tập hợp con trang mẫu.

Phần có liên quan của tập lệnh nối - giả sử inputslà danh sách các tên tệp đầu vào và outfnlà tên tệp đầu ra:

from pdfrw import PdfReader, PdfWriter

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

Như bạn có thể thấy từ điều này, sẽ khá dễ dàng để bỏ qua trang cuối cùng, ví dụ như một cái gì đó như:

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

Tuyên bố từ chối trách nhiệm: Tôi là pdfrwtác giả chính .


1
Đây là cái ổn định nhất.
GoingMyWay

1
Thư viện này xứng đáng với danh tiếng hơn.
GoingMyWay

6

Có thể sử dụng Python để hợp nhất các tệp PDF riêng biệt không?

Đúng.

Ví dụ sau hợp nhất tất cả các tệp trong một thư mục thành một tệp PDF mới:

#!/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

tại đây, http://pieceofpy.com/2009/03/05/concatenating-pdf-with-python/ , đưa ra giải pháp.

tương tự:

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

Một biến thể nhỏ bằng cách sử dụng từ điển để linh hoạt hơn (ví dụ: sắp xếp, loại bỏ):

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

Tôi đã sử dụng hợp nhất pdf trên thiết bị đầu cuối linux bằng cách tận dụng quy trình con (giả sử có một.pdf và hai.pdf trên thư mục) và mục đích là hợp nhất chúng thành ba.pdf

 import subprocess
 subprocess.call(['pdfunite one.pdf two.pdf three.pdf'],shell=True)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.