รวมไฟล์ 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')
Simeon Borko

@SimeonBorko วาง+มันหมายถึง "อ่านและเขียน" และไฟล์ทั้งสองไม่มีทั้งอ่านและเขียน ฉันได้เพิ่มการสนับสนุนการสนับสนุนการส่งออกของ Windows บนพื้นฐานstackoverflow.com/questions/2374427/...
Gilles 'SO- หยุดชั่ว'

PyPDF2 / 3 ไม่เสถียรฉันจะรวมไฟล์ pdf โดยไม่ใช้ PyPDF2 / 3 ได้อย่างไร
GoingMyWay

2
ฉันต้องใช้sys.stdout.bufferโดยใช้ Python 3.6.8 (Linux)
Greyshack

198

คุณสามารถใช้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ควรเรียกใช้วิธีการปิดเมื่อไฟล์ที่ผสานถูกเขียน เพื่อให้แน่ใจว่าไฟล์ทั้งหมดจะปิด (อินพุตและเอาต์พุต) ในเวลาที่เหมาะสม เป็นเรื่องน่าเสียดายที่PdfFileMergerไม่ได้ใช้เป็นตัวจัดการบริบทดังนั้นเราจึงสามารถใช้withคีย์เวิร์ดหลีกเลี่ยงการโทรปิดอย่างชัดเจนและได้รับความปลอดภัยจากข้อยกเว้นง่ายๆ

คุณอาจต้องการดูpdfcatสคริปต์ที่ให้ไว้เป็นส่วนหนึ่งของ pypdf2 คุณอาจหลีกเลี่ยงความจำเป็นในการเขียนโค้ดทั้งหมดได้

PyPdf2 github ยังมีโค้ดตัวอย่างบางส่วนที่แสดงการรวมเข้าด้วยกัน


15

รวมไฟล์ pdf ทั้งหมดที่มีอยู่ใน dir

ใส่ไฟล์ pdf ใน dir เปิดโปรแกรม คุณจะได้รับ 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])

Disclaimer: ฉันเป็น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 โดยใช้ประโยชน์จากกระบวนการย่อย (สมมติว่า one.pdf และ two.pdf มีอยู่ในไดเร็กทอรี) และจุดมุ่งหมายคือการรวมเข้ากับ three.pdf

 import subprocess
 subprocess.call(['pdfunite one.pdf two.pdf three.pdf'],shell=True)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.