import os
import re
import pdfplumber
from PyPDF2 import PdfReader, PdfWriter
# ======= 需要先改的配置 =======
# 1. 源 PDF 路徑(你的合併後PDF)
INPUT_PDF = r"./merged.pdf" # ← 改成你的檔案路徑
# 2. 輸出資料夾(會自動建立)
OUTPUT_DIR = r"./split_output"
# 3. 代號格式:像 "1A-1"、"6D-32" 的樣子
# 數字(1+) + 大寫字母(1) + "-" + 數字(1+)
CODE_PATTERN = r"\b\d+[A-Z]-\d+\b"
# 4. 一份文件預期頁數(你說每人兩頁)
PAGES_PER_DOC = 2
# ===============================
os.makedirs(OUTPUT_DIR, exist_ok=True)
def extract_last_code_from_page(pdfpl_page, pattern):
"""
從 pdfplumber 的 page 物件中提取文本,
找出最後一個匹配 pattern 的字串 (例如 1A-1),
找不到則回傳 None。
"""
text = pdfpl_page.extract_text() or ""
matches = re.findall(pattern, text)
if not matches:
return None
return matches[-1]
def save_pdf_segment(reader, start_idx, end_idx_inclusive, code, output_dir):
"""
將 reader 中從 start_idx 到 end_idx_inclusive (包含) 這些頁
合併輸出成一份 PDF,檔名為 <code>.pdf,
並放在 <output_dir>/<code>/ 這個子目錄裡。
"""
writer = PdfWriter()
for idx in range(start_idx, end_idx_inclusive + 1):
writer.add_page(reader.pages[idx])
# 檔名安全處理(避免奇怪字元)
safe_code = re.sub(r'[\\/*?:"<>|]', '_', code)
# 以代號建立子資料夾: output_dir / safe_code
code_dir = os.path.join(output_dir, safe_code)
os.makedirs(code_dir, exist_ok=True)
# PDF 檔案路徑: output_dir / safe_code / safe_code.pdf
out_path = os.path.join(code_dir, f"{safe_code}.pdf")
with open(out_path, "wb") as f:
writer.write(f)
print(f"✔ 輸出檔案:{out_path}(頁數:{end_idx_inclusive - start_idx + 1})")
def main():
# 同時用 pdfplumber (抽文字) + PyPDF2 (拆頁、存檔)
pdfpl_doc = pdfplumber.open(INPUT_PDF)
pypdf_reader = PdfReader(open(INPUT_PDF, "rb"))
num_pages = len(pdfpl_doc.pages)
print(f"總頁數:{num_pages}")
# 遍歷所有頁,當發現某頁有代碼,就向前取固定頁數
for i in range(num_pages):
pl_page = pdfpl_doc.pages[i]
page_code = extract_last_code_from_page(pl_page, CODE_PATTERN)
print(f"第 {i+1} 頁 → 代碼:{page_code}")
if page_code is None:
# 這頁沒有代碼 → 什麼都不做(它會被「後一頁的代碼」一起抓走)
continue
# 有代碼的這一頁被視為「某一份文件的最後一頁」
# 假設一份文件固定為 PAGES_PER_DOC 頁:
# start = i - (PAGES_PER_DOC - 1)
# end = i
start_idx = i - (PAGES_PER_DOC - 1)
end_idx = i
# 防呆:如果 start_idx < 0,就從 0 開始
if start_idx < 0:
print(f" ⚠️ 代碼 {page_code} 的起始頁計算為 {start_idx+1},小於 1,改為從第 1 頁開始。")
start_idx = 0
save_pdf_segment(
reader=pypdf_reader,
start_idx=start_idx,
end_idx_inclusive=end_idx,
code=page_code,
output_dir=OUTPUT_DIR
)
pdfpl_doc.close()
print("全部處理完成。")
if __name__ == "__main__":
main()