"""PDF 텍스트 줄 단위 추출 도우미.""" import re import unicodedata from dataclasses import dataclass import pymupdf @dataclass class Line: page: int x: float y: float x1: float size: float font: str text: str def clean(s: str) -> str: s = unicodedata.normalize("NFC", s) s = "".join(c for c in s if c in "\n\t" or unicodedata.category(c)[0] != "C") s = s.replace(" ", " ").replace(" ", " ").replace(" ", " ") s = s.replace("ᝍ", "-").replace("․", "·") return re.sub(r"\s+", " ", s).strip() def page_lines(doc: pymupdf.Document, i: int) -> list[Line]: out = [] for b in doc[i].get_text("dict")["blocks"]: for l in b.get("lines", []): spans = l["spans"] if not spans: continue text = clean("".join(s["text"] for s in spans)) if not text: continue x0, y0, x1, _ = l["bbox"] out.append(Line(i, x0, y0, x1, spans[0]["size"], spans[0]["font"], text)) return out def print_label(doc: pymupdf.Document, i: int) -> str: return doc[i].get_label() or str(i + 1) def label_to_index(doc: pymupdf.Document) -> dict[str, int]: """인쇄 페이지 번호(라벨) → PDF 파일상 0-based 페이지. 아라비아 숫자 라벨만.""" m = {} for i in range(len(doc)): lab = doc[i].get_label() or str(i + 1) if lab.isdigit() and lab not in m: m[lab] = i return m def body_text(doc: pymupdf.Document, i: int) -> str: """머리말·꼬리말을 뺀 본문 텍스트. 줄바꿈으로 끊긴 단어를 이어 붙임.""" h = doc[i].rect.height parts = [] for b in doc[i].get_text("dict")["blocks"]: buf = "" for l in b.get("lines", []): y = l["bbox"][1] if y < 50 or y > h - 45: continue raw = unicodedata.normalize("NFC", "".join(s["text"] for s in l["spans"])) if not raw.strip(): continue if buf and not buf.endswith(" ") and not raw.startswith(" "): # 한글끼리 줄이 바뀌면 단어 중간에서 끊긴 것으로 보고 붙인다 if not (_is_hangul(buf[-1]) and _is_hangul(raw[0])): buf += " " buf += raw t = clean(buf) if t: parts.append(t) return "\n".join(parts) def _is_hangul(c: str) -> bool: return "가" <= c <= "힣"