Perfis de extração — ajuste a detecção de espaços por tipo de documento
PDFs diferentes escondem os espaços de formas diferentes. Um artigo do arXiv usa colunas justificadas e apertadas. Um formulário do IRS depende de alinhamento rígido de células. Uma política GDPR se espalha em parágrafos densos e justificados com kerning mínimo. Um único tj_offset_threshold que funciona para um desses casos vai injetar espaços falsos nos outros.
ExtractionProfile traz nove conjuntos de parâmetros pré-ajustados que mapeiam direto em classes reais de documento. Passe o perfil para extract_text() ou extract_words() e o PDF Oxide aplica a razão de margem de palavra, o threshold de offset TJ e o flag de threshold adaptativo adequados para aquele estilo de documento.
Cobertura por binding. Os perfis de extração estão expostos atualmente em Python (
pdf_oxide.ExtractionProfile) e Rust (pdf_oxide::config::ExtractionProfile). Os bindings de Node, WASM, Go e C# usam internamente o padrãoCONSERVATIVE; para aplicar outro perfil a partir desses runtimes, invoque a CLI em Rust (pdf-oxide extract --profile academic doc.pdf) ou encadeie com uma etapa em Python / Rust.
Exemplo rápido
Python
from pdf_oxide import PdfDocument, ExtractionProfile
doc = PdfDocument("paper.pdf")
# Artigos acadêmicos: espaçamento apertado, detecção de citações ligada
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);
Perfis disponíveis
| Perfil | Melhor para | Threshold TJ | Razão de margem de palavra | Adaptativo |
|---|---|---|---|---|
conservative() |
Padrão — texto geral, mínimo de espaços falsos | −120 | 0,10 | off |
aggressive() |
PDFs que suprimem espaços; corrige palavras coladas | −80 | 0,20 | off |
balanced() |
Conteúdo misto | −100 | 0,15 | off |
academic() |
Artigos do arXiv, anais de conferência, relatórios técnicos | −105 | 0,12 | on + detecção de citações / e-mails |
policy() |
Legal, GDPR, regulamentações governamentais | −110 | 0,18 | on |
form() |
Formulários IRS, requerimentos, questionários | −120 | 0,08 | off |
government() |
Relatórios governamentais mistos com tabelas | −105 | 0,14 | off |
scanned_ocr() |
Saída de OCR com coordenadas ruidosas | depende | depende | on |
adaptive() |
Deixa o extrator se ajustar a partir das estatísticas da fonte | depende | depende | on |
Quando cada perfil ajuda
Artigos acadêmicos / conferência — academic()
Composição apertada, layouts de duas colunas, citações embutidas. As configurações padrão costumam inserir espaços a mais dentro de ligaduras (fi, ff) ou a menos entre palavras onde o kerning é agressivo.
doc = PdfDocument("neurips-paper.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.academic())
O perfil acadêmico liga o threshold adaptativo junto com a detecção de citações e e-mails, de modo que referências inline [1,2,3] e e-mails como author@lab.edu sobrevivem limpos.
Formulários IRS, requerimentos — form()
PDFs de formulário se importam mais com o alinhamento das colunas do que com os limites entre palavras. O perfil form() usa uma razão de margem de palavra bem apertada (0,08) para que rótulos de campo rigidamente alinhados não colapsem com os valores.
doc = PdfDocument("w2.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.form())
GDPR / políticas / regulação — policy()
Parágrafos justificados inserem espaçamento variável que quebra o threshold padrão. policy() usa uma margem de palavra mais generosa (0,18) com threshold adaptativo para ler corretamente textos jurídicos densos.
doc = PdfDocument("gdpr.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.policy())
Saída de OCR digitalizada — scanned_ocr()
Quando a página passou por OCR (Tesseract, PaddleOCR, Azure), as posições dos caracteres ficam ruidosas e as dicas de kerning somem. scanned_ocr() compensa com threshold adaptativo que relê as estatísticas da fonte a cada página.
doc = PdfDocument("scanned.pdf")
text = doc.extract_text(0, profile=ExtractionProfile.scanned_ocr())
Deixe a biblioteca escolher — adaptive()
Se você não sabe de antemão a classe do documento, adaptive() faz uma amostragem das estatísticas da fonte na primeira passada e define os thresholds antes de extrair. Um pouco mais lento do que um perfil fixo, mas tolerante em corpus mistos.
for pdf_path in Path("mixed_corpus/").glob("*.pdf"):
doc = PdfDocument(str(pdf_path))
text = doc.extract_text(0, profile=ExtractionProfile.adaptive())
Campos do perfil
Cada perfil expõe seus ajustes para você ler ou clonar:
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
# Inspecionar todos os presets
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);
Escolhendo um perfil em pipelines de produção
Se você ingere um corpus misto — artigos acadêmicos ao lado de formulários IRS ao lado de exports HTML raspados da web — escolha adaptive() como padrão. Custa um pouco a mais por página, mas elimina as piores falhas (palavras coladas, espaços ausentes entre colunas).
Se o seu corpus é homogêneo — uma pipeline de intake de Title IX, uma ferramenta de revisão contratual, um crawler de arXiv — escolha o perfil correspondente explicitamente: você obtém a melhor qualidade de extração e evita o custo de amostragem por página do adaptive().
Páginas relacionadas
- Extração de texto — API completa de extração
- Ordem de leitura (XY-cut) — ordem de leitura ciente de colunas
- OCR em PDFs digitalizados — quando o perfil sozinho não basta
- Referência da API Python