PDF 文件拆分技巧:用 Python 實現書籤與頁數分割
前言
在工作上不免會遇到需要將一大份的pdf切割成很多小的檔案,常見的切割方式為透過書籤進行切割,又或者是透過頁數進行切割,本文將針對以下兩種情況進行python範例介紹。
使用前說明
使用本程式需先安裝PyMuPDF,PyMuPDF是一個python用來處理pdf的套件
可透過pip install 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)