學藝比賽 – 第一階段合併出eclass

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