小學新生銜接課程-PDF折分及命名python
功能:滑動兩頁:1-2、2-3…;用最後一頁底部 key 命名
安裝套件
pip install pypdf pdfplumber
pypdf:負責拆分/寫出新 PDF
pdfplumber:負責抽文字(比較適合抓某個區域例如頁面底部)
提示詞(可直接複製貼上)
你是一位資深 Python 工程師,請幫我寫一個可執行的 Python 腳本,需求如下(請一次整合完成):
- 輸入檔固定為
all.pdf(與腳本同資料夾)。 - 將 PDF 不重疊拆分成每段 2 頁:
1-2、3-4、5-6...(以原 PDF 頁序)。 - 每段輸出檔名要用「該段最後一頁(也就是偶數頁)」右下角底部的數字 key來命名,例如讀到
26271009就輸出26271009.pdf。 - 不能用 OCR。請用
pdfplumber讀取文字,且請優先使用page.chars依座標篩選右下角字元,再把字元串起來,用正則抽出最後一段數字當 key(不要只用extract_text(),因為有些 PDF 會讀不到)。 - 右下角讀取範圍請用比例參數控制(例如
BOTTOM_RATIO、RIGHT_RATIO),並在程式開頭可調;預設值給一組合理的(例如 bottom 0.22、right 0.45)。 - 若某段抓不到 key,輸出檔名請用
UNKNOWN_頁碼.pdf(頁碼指該段最後一頁的 1-based 頁碼,例如UNKNOWN_0002.pdf)。 - 若 key 重複避免覆蓋:自動加尾碼
_2,_3(例如26271009_2.pdf)。 - 若原 PDF 總頁數為奇數:最後單頁可忽略,但需在 console 印出提示。
- 輸出到資料夾
out_split/(不存在就建立)。 - 請使用
pypdf寫出拆分後 PDF,pdfplumber讀 key。附上pip install指令與執行方式。
請給我:完整可執行程式碼(單檔即可),並用清楚的註解解釋每個步驟。
import re
from pathlib import Path
from pypdf import PdfReader, PdfWriter
import pdfplumber
KEY_REGEX = r"\b(\d{8})\b"
def sanitize_filename(s: str) -> str:
s = (s or "").strip()
s = re.sub(r"\s+", " ", s)
s = re.sub(r'[\\/:"*?<>|]+', "_", s)
return s.strip(" ._")
def extract_key_from_page_tail(pdf_path: str, page_index: int, tail_lines: int = 25, debug: bool = False):
with pdfplumber.open(pdf_path) as pdf:
text = (pdf.pages[page_index].extract_text() or "")
# 去掉常見雜訊符號(可再加)
text = text.replace("\uF026", " ")
lines = [ln.strip() for ln in text.splitlines() if ln.strip()]
tail = "\n".join(lines[-tail_lines:])
m = re.search(KEY_REGEX, tail)
if debug:
print(f"[DEBUG] page={page_index+1} tail=\n---\n{tail}\n---\nmatch={m.group(1) if m else None}\n")
return m.group(1) if m else None
def unique_path(p: Path) -> Path:
if not p.exists():
return p
i = 2
while True:
cand = p.with_name(f"{p.stem}_{i}{p.suffix}")
if not cand.exists():
return cand
i += 1
def split_every_two(pdf_path="all.pdf", out_dir="out", debug=False):
out_dir = Path(out_dir)
out_dir.mkdir(parents=True, exist_ok=True)
reader = PdfReader(pdf_path)
n = len(reader.pages)
for start in range(0, n, 2):
end = min(start + 2, n)
writer = PdfWriter()
for i in range(start, end):
writer.add_page(reader.pages[i])
# 先用第1頁,抓不到再用第2頁
key = extract_key_from_page_tail(pdf_path, start, debug=debug)
if key is None and end - 1 != start:
key = extract_key_from_page_tail(pdf_path, end - 1, debug=debug)
if key is None:
key = f"pages_{start+1}-{end}"
key = sanitize_filename(key)
out_path = unique_path(out_dir / f"{key}.pdf")
with open(out_path, "wb") as f:
writer.write(f)
print(f"輸出: {out_path.name} (頁 {start+1}-{end}, key={key})")
if __name__ == "__main__":
split_every_two("all.pdf", "out", debug=True)