Skip to content

Профілі видобування — налаштування розпізнавання пробілів під тип документа

Різні 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().

Пов’язані сторінки