추출 프로파일 — 문서 종류별 공백 감지 튜닝
PDF마다 공백을 숨겨두는 방식이 다릅니다. arXiv 논문은 빽빽한 양쪽 정렬의 다단으로 조판되고, IRS 양식은 셀 정렬에 엄격하게 의존하며, GDPR 정책 문서는 최소한의 커닝만으로 양쪽 정렬된 빽빽한 문단을 흘려 넣습니다. 한쪽에 맞춘 tj_offset_threshold 하나만으로는 다른 쪽에서 엉뚱한 공백이 끼어듭니다.
ExtractionProfile은 실제 문서 클래스에 깔끔하게 대응하는 사전 조정된 아홉 가지 파라미터 세트를 제공합니다. 프로파일을 extract_text()나 extract_words()에 넘기면, PDF Oxide가 해당 문서 스타일에 맞는 단어 margin 비율, TJ offset 임계값, 적응형 임계값 on/off를 적용합니다.
바인딩 지원 범위. 추출 프로파일은 현재 Python (
pdf_oxide.ExtractionProfile)과 Rust (pdf_oxide::config::ExtractionProfile)에서 노출되어 있습니다. Node, WASM, Go, C# 바인딩은 내부적으로CONSERVATIVE기본값을 사용합니다. 이 런타임에서 다른 프로파일을 적용하려면 Rust CLI(pdf-oxide extract --profile academic doc.pdf)를 호출하거나, Python / Rust 단계를 거쳐 연결하세요.
빠른 예제
Python
from pdf_oxide import PdfDocument, ExtractionProfile
doc = PdfDocument("paper.pdf")
# 학술 논문: 좁은 자간, 인용 감지 활성화
text = doc.extract_text(0, profile=ExtractionProfile.academic())
print(text)
Rust
use pdf_oxide::PdfDocument;
use pdf_oxide::config::ExtractionProfile;
let mut doc = PdfDocument::open("paper.pdf")?;
let text = doc.extract_text_with_profile(0, ExtractionProfile::ACADEMIC)?;
println!("{}", text);
사용 가능한 프로파일
| 프로파일 | 권장 용도 | TJ 임계값 | 단어 margin 비율 | 적응형 |
|---|---|---|---|---|
conservative() |
기본값 — 일반 텍스트, 불필요한 공백 최소 | −120 | 0.10 | off |
aggressive() |
공백이 억제된 PDF, 붙어 있는 단어 분리 | −80 | 0.20 | off |
balanced() |
혼합 콘텐츠 | −100 | 0.15 | off |
academic() |
arXiv 논문, 학회 프로시딩, 기술 보고서 | −105 | 0.12 | on + 인용 / 이메일 감지 |
policy() |
법률, GDPR, 정부 규정 | −110 | 0.18 | on |
form() |
IRS 양식, 신청서, 설문지 | −120 | 0.08 | off |
government() |
표가 포함된 정부 보고서 | −105 | 0.14 | off |
scanned_ocr() |
좌표가 노이즈 섞인 OCR 출력 | 자동 | 자동 | on |
adaptive() |
폰트 통계로부터 추출기가 자동 튜닝 | 자동 | 자동 | on |
프로파일별 효과
학술 논문 / 학회 프로시딩 — academic()
빽빽한 조판, 2단 레이아웃, 문장 내 인용이 섞여 있습니다. 기본 설정으로는 합자(fi, ff) 안에 공백이 더 들어가거나, 커닝이 강한 단어 사이에서는 공백이 모자라기 쉽습니다.
doc = PdfDocument("neurips-paper.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.academic())
학술용 프로파일은 적응형 임계값과 함께 인용 / 이메일 감지를 켜기 때문에, [1,2,3] 같은 인라인 참조와 author@lab.edu 같은 이메일 주소가 온전히 유지됩니다.
IRS 양식, 신청서 — form()
양식 PDF는 단어 경계보다 열 정렬을 중요하게 여깁니다. form() 프로파일은 아주 좁은 단어 margin 비율(0.08)을 사용해, 엄격하게 정렬된 필드 라벨이 그 값과 합쳐지지 않도록 합니다.
doc = PdfDocument("w2.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.form())
GDPR / 정책 / 규정 — policy()
양쪽 정렬된 문단은 가변 폭의 공백이 삽입되어 기본 임계값을 무너뜨립니다. policy()는 더 넉넉한 단어 margin(0.18)과 적응형 임계값을 함께 써서 빽빽한 법률 문장을 정확히 읽어 냅니다.
doc = PdfDocument("gdpr.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.policy())
스캔 OCR 출력 — scanned_ocr()
페이지가 OCR(Tesseract, PaddleOCR, Azure)로 만들어졌다면, 문자 좌표에 노이즈가 섞이고 커닝 힌트가 사라집니다. scanned_ocr()는 페이지마다 폰트 통계를 다시 읽는 적응형 임계값으로 이를 보완합니다.
doc = PdfDocument("scanned.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.scanned_ocr())
라이브러리에 맡기기 — adaptive()
문서 클래스를 사전에 알 수 없다면 adaptive()가 첫 패스에서 폰트 통계를 샘플링하고 추출 전에 임계값을 결정합니다. 고정 프로파일보다 조금 느리지만 혼합 코퍼스에 관대합니다.
for pdf_path in Path("mixed_corpus/").glob("*.pdf"):
doc = PdfDocument(str(pdf_path))
text = doc.extract_text(0, profile=ExtractionProfile.adaptive())
프로파일 필드
각 프로파일은 튜닝 파라미터를 공개하므로, 값을 읽거나 복제할 수 있습니다.
Python
from pdf_oxide import ExtractionProfile
p = ExtractionProfile.academic()
print(p.name) # "Academic"
print(p.word_margin_ratio) # 0.12
print(p.tj_offset_threshold) # -105.0
# 모든 프리셋 확인
for profile in ExtractionProfile.all_profiles():
print(profile.name, profile.word_margin_ratio)
Rust
use pdf_oxide::config::ExtractionProfile;
let p = ExtractionProfile::ACADEMIC;
println!("{} margin={} tj={}",
p.name, p.word_margin_ratio, p.tj_offset_threshold);
프로덕션 파이프라인에서의 프로파일 선택
혼합 코퍼스(학술 논문, IRS 양식, 웹 크롤링된 HTML 내보내기 등)를 받아들인다면 기본값으로 adaptive()를 고르는 것이 안전합니다. 페이지당 몇 퍼센트의 오버헤드가 생기지만, 단어가 붙어 버리거나 단 사이에 공백이 빠지는 최악의 실패를 줄일 수 있습니다.
동질 코퍼스(Title IX 접수 파이프라인, 계약 검토 도구, arXiv 크롤러 등)라면 해당 프로파일을 명시적으로 지정하세요. 최고의 추출 품질을 얻으면서 adaptive()의 페이지당 샘플링 비용도 피할 수 있습니다.
관련 페이지
- 텍스트 추출 — 전체 추출 API
- 읽기 순서(XY-cut) — 단 인식 읽기 순서
- 스캔 PDF의 OCR — 프로파일만으로 부족할 때
- Python API 레퍼런스