Профілі видобування — налаштування розпізнавання пробілів під тип документа
Різні PDF ховають пробіли по-різному. Стаття з arXiv набирається щільними колонками з вирівнюванням по ширині. Форма IRS тримається на жорсткій сітці клітинок. Документ GDPR — це щільний юридичний текст по ширині з мінімальним кернінгом. Один tj_offset_threshold, підібраний під один випадок, в іншому буде вставляти зайві пробіли.
ExtractionProfile містить дев’ять попередньо налаштованих наборів параметрів, які чітко відповідають реальним класам документів. Передайте профіль у extract_text() або extract_words(), і PDF Oxide застосує відповідне співвідношення word-margin, поріг TJ-offset та перемикач адаптивного порогу саме для цього стилю документа.
Підтримка в біндингах. Профілі видобування зараз доступні в 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 | Word-margin ratio | Адаптивний |
|---|---|---|---|---|
conservative() |
За замовчуванням — звичайний текст, мінімум зайвих пробілів | −120 | 0,10 | вимк. |
aggressive() |
PDF зі злитими словами; розбиває склеєні слова | −80 | 0,20 | вимк. |
balanced() |
Змішаний контент | −100 | 0,15 | вимк. |
academic() |
Статті arXiv, матеріали конференцій, технічні звіти | −105 | 0,12 | увімк. + розпізнавання цитат / e-mail |
policy() |
Юридичні документи, GDPR, державні регламенти | −110 | 0,18 | увімк. |
form() |
Форми IRS, заяви, анкети | −120 | 0,08 | вимк. |
government() |
Державні звіти з таблицями | −105 | 0,14 | вимк. |
scanned_ocr() |
Результат OCR із шумними координатами | залежить | залежить | увімк. |
adaptive() |
Екстрактор сам налаштовується за статистикою шрифтів | залежить | залежить | увімк. |
Коли потрібен кожен профіль
Наукові статті та матеріали конференцій — academic()
Щільний набір, двоколонкова верстка, вбудовані цитати. За замовчуванням між лігатурами (fi, ff) часто з’являються зайві пробіли, а там, де кернінг сильний, навпаки губляться.
doc = PdfDocument("neurips-paper.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.academic())
Академічний профіль вмикає адаптивний поріг разом із розпізнаванням цитат і e-mail, тож рядкові посилання вигляду [1,2,3] та адреси типу author@lab.edu зберігаються в чистому вигляді.
Форми IRS, заяви — form()
Для PDF-форм важливіше зберегти вирівнювання колонок, ніж межі слів. Профіль form() використовує дуже вузьке співвідношення word-margin (0,08), аби жорстко вирівняні підписи полів не зливалися зі значеннями.
doc = PdfDocument("w2.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.form())
GDPR / регламенти / юридичні документи — policy()
У тексті, вирівняному по ширині, вставляються пробіли змінної ширини, через що поріг за замовчуванням ламається. policy() використовує щедріше значення word-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) — порядок читання з урахуванням колонок
- OCR для сканованих PDF — коли одного профілю замало
- Довідник Python API