|

PDF 文件拆分技巧:用 Python 實現書籤與頁數分割

前言

在工作上不免會遇到需要將一大份的pdf切割成很多小的檔案,常見的切割方式為透過書籤進行切割,又或者是透過頁數進行切割,本文將針對以下兩種情況進行python範例介紹。

使用前說明

使用本程式需先安裝PyMuPDF,PyMuPDF是一個python用來處理pdf的套件

可透過pip install PyMuPDF進行安裝,

安裝完成後我們確認一下是否成功

import fitz
print(fitz.__doc__)

若有輸出類似以下的畫面表示有成功安裝

PyMuPDF安裝成功後執行import fitz
print(fitz.__doc__)會出現版本號及說明

依據書籤進行切割主程式

藉由以下程式即可將pdf依照書籤進行切割,還可以透過設定要切割的書籤層級(可以調整target_level )進行切割

import fitz  # PyMuPDF
import os

def split_pdf_by_bookmarks(input_pdf, output_dir, target_level=1):
    # 確保輸出資料夾存在
    os.makedirs(output_dir, exist_ok=True)
    
    # 開啟 PDF 檔案
    pdf_document = fitz.open(input_pdf)
    bookmarks = pdf_document.get_toc()  # 獲取書籤目錄
    
    if not bookmarks:
        print("此 PDF 沒有書籤。")
        return
    
    for i, (level, title, page) in enumerate(bookmarks):
        # 篩選指定層級的書籤
        if level != target_level:
            continue
        
        start_page = page - 1  # 書籤頁面(從1開始)
        end_page = (
            bookmarks[i + 1][2] - 1 if i + 1 < len(bookmarks) and bookmarks[i + 1][0] == level else pdf_document.page_count
        )
        
        # 確保範圍有效
        '''
        1.起始頁不能大於或等於結束頁。
        2.起始頁不能小於 0。
        3.結束頁不能超出 PDF 文件的總頁數。
        '''
        if start_page >= end_page or start_page < 0 or end_page > pdf_document.page_count:
            print(f"略過無效範圍的書籤: {title}")
            continue

        # 提取範圍內的頁面
        pdf_subset = fitz.open() #建立一個pdf
        for p in range(start_page, end_page):#將範圍內的頁數放入建立的pdf中
            pdf_subset.insert_pdf(pdf_document, from_page=p, to_page=p)
        
        # 清理標題以適合作為檔案名
        '''
        程式說明:
        for c in title :每次迴圈都取 title 中的一個字元 c
        條件判斷:
        c if c.isalnum() or c in " _-" else "_"
        如果 c 是字母或數字(isalnum()),或者屬於空格、底線或連字符(" _-"),則保留 c 本身
				,否則,將 c 替換成底線 _。
				最後:
				"".join(...)將處理後的每個字元連接起來,形成新的字串
        '''
        safe_title = "".join(c if c.isalnum() or c in " _-" else "_" for c in title)
        output_path = os.path.join(output_dir, f"{safe_title}.pdf")
        
        # 儲存檔案
        pdf_subset.save(output_path)
        print(f"已儲存: {output_path}")
        pdf_subset.close()
    
    pdf_document.close()
    print("所有書籤處理完成!")

input_pdf = "欲切割之pdf路徑"
output_dir = "./split_pdfs"#切割後之pdf儲存路徑
target_level = 1 #欲切割之書籤層級
split_pdf_by_bookmarks(input_pdf, output_dir,target_level)

依據頁數進行切割主程式

import fitz  # PyMuPDF
import os

def split_pdf_by_pages(input_pdf, output_dir, pages_per_split):
    
    # 確保輸出資料夾存在
    os.makedirs(output_dir, exist_ok=True)

    # 開啟 PDF 檔案
    pdf_document = fitz.open(input_pdf)
    total_pages = pdf_document.page_count

    # 計算切割數量
    num_splits = (total_pages + pages_per_split - 1) // pages_per_split  # 無條件進位計算分組數量

    for i in range(num_splits):
        start_page = i * pages_per_split
        end_page = min(start_page + pages_per_split, total_pages)  # 確保不超過總頁數

        # 建立新的 PDF
        pdf_subset = fitz.open()
        for p in range(start_page, end_page):
            pdf_subset.insert_pdf(pdf_document, from_page=p, to_page=p)

        # 儲存切割後的 PDF
        output_path = os.path.join(output_dir, f"split_{i + 1}.pdf")
        pdf_subset.save(output_path)
        print(f"已儲存: {output_path}")
        pdf_subset.close()

    pdf_document.close()
    print("所有頁面切割完成!")

# 範例用法
input_pdf = "欲切割之pdf路徑"
output_dir = "./split_pdfs"  # 切割後之 PDF 儲存路徑
pages_per_split = 10  # 每個切割的 PDF 包含 10 頁
split_pdf_by_pages(input_pdf, output_dir, pages_per_split)

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *