Extração de Texto
O PDF Oxide oferece múltiplos níveis de extração de texto: texto completo da página, spans estilizados com metadados de fonte e caracteres individuais com posicionamento preciso. Use extract_text() para recuperar conteúdo rapidamente, extract_spans() quando precisar de dados de fonte e posição, e extract_chars() para análise caractere a caractere — como em mecanismos de layout customizados ou pós-processamento de OCR.
Para PDFs com tags, a extração de texto segue automaticamente a árvore de estrutura do documento para garantir a ordem de leitura correta. Para PDFs sem tags, a extração usa a ordem do conteúdo da página com detecção inteligente de quebras de linha — incluindo uma proteção de coluna única que evita a fragmentação do corpo de texto em documentos no estilo RFC e dissertações.
Suporte à ordem de leitura
O pipeline de ordem de leitura produz saídas corretas para diferentes scripts e layouts:
- Latin — padrão da esquerda para a direita e de cima para baixo, com detecção de colunas.
- Arabic — a inversão de spans pré-moldados (Pass 0) coloca os caracteres na ordem de leitura lógica em vez da visual.
- CJK — o detector espacial de tabelas preserva colunas com rótulos rowspan; a quantização de 3pt no eixo Y evita que conteúdo tabular se misture ao texto corrido.
- PDFs rotacionados / gerados por dvips — a rejeição de outliers baseada em mediana na detecção de colunas trata coordenadas CTM degeneradas.
- Artigos acadêmicos multicolunas — a proteção de coluna única XYCut corrige a fragmentação; a ordenação de spans com consciência de linha trata conteúdo tabular dentro de blocos de texto.
Segmentação de palavras e linhas
extract_words() e extract_text_lines() aceitam argumentos de palavra-chave opcionais para ajustar os limiares de quebra de palavras e linhas:
| Parâmetro | Padrão | Descrição |
|---|---|---|
word_gap_threshold |
adaptativo | Espaço horizontal mínimo (em pontos) entre caracteres adjacentes para contar como quebra de palavra |
line_gap_threshold |
adaptativo | Espaço vertical mínimo entre linhas de base para contar como quebra de linha |
profile |
"auto" |
Um de "auto", "dense", "standard", "sparse" — seleciona um preset ajustado para diferentes layouts |
Os parâmetros adaptativos são derivados das métricas de fonte da página. Use page_layout_params() para inspecionar os valores calculados e ExtractionProfile para criar um perfil customizado.
Ajuste exclusivo do Python:
word_gap_threshold,line_gap_threshold,profileepage_layout_params()estão disponíveis no binding Python. Os bindings de Node.js, JavaScript, Go, C# e WASM expõemextractWords(pageIndex)/extractTextLines(pageIndex)usando os padrões adaptativos sem kwargs. Para ajuste a partir dessas linguagens, use a API Rust abaixo.
Python
from pdf_oxide import PdfDocument, ExtractionProfile
doc = PdfDocument("receipt.pdf")
params = doc.page_layout_params(0)
print(params.word_gap_threshold, params.line_gap_threshold)
words = doc.extract_words(0, word_gap_threshold=2.5, profile="dense")
lines = doc.extract_text_lines(0, profile=ExtractionProfile.DENSE)
Node.js
const { PdfDocument } = require("pdf-oxide");
const doc = new PdfDocument("receipt.pdf");
const words = doc.extractWords(0); // adaptive defaults
const lines = doc.extractTextLines(0);
doc.close();
JavaScript
const { PdfDocument } = require("pdf-oxide");
const doc = new PdfDocument("receipt.pdf");
const words = doc.extractWords(0);
const lines = doc.extractTextLines(0);
doc.close();
TypeScript
import { PdfDocument } from "pdf-oxide";
const doc: PdfDocument = new PdfDocument("receipt.pdf");
const words = doc.extractWords(0);
const lines = doc.extractTextLines(0);
doc.close();
Rust
use pdf_oxide::{PdfDocument, ExtractionProfile};
let mut doc = PdfDocument::open("receipt.pdf")?;
let params = doc.page_layout_params(0)?;
println!("{} {}", params.word_gap_threshold, params.line_gap_threshold);
let words = doc.extract_words_with_config(0, /* word_gap_threshold */ Some(2.5), ExtractionProfile::Dense)?;
let lines = doc.extract_text_lines_with_profile(0, ExtractionProfile::Dense)?;
Go
words, _ := doc.ExtractWords(0) // adaptive defaults
lines, _ := doc.ExtractTextLines(0)
C#
var words = doc.ExtractWords(0); // adaptive defaults
var lines = doc.ExtractTextLines(0);
WASM
const doc = new WasmPdfDocument(bytes);
const words = doc.extractWords(0);
const lines = doc.extractTextLines(0);
Java
try (PdfDocument doc = PdfDocument.open(Path.of("receipt.pdf"))) {
List<TextWord> words = doc.page(0).words(); // adaptive defaults
List<TextLine> lines = doc.page(0).lines();
}
C++
auto doc = pdf_oxide::Document::open("receipt.pdf");
auto words = doc.extract_words(0); // adaptive defaults
auto lines = doc.extract_text_lines(0);
Swift
let doc = try Document.open("receipt.pdf")
let words = try doc.extractWords(0) // adaptive defaults
let lines = try doc.extractTextLines(0)
Kotlin
PdfDocument.open(Path.of("receipt.pdf")).use { doc ->
val words = doc.page(0).words() // adaptive defaults
val lines = doc.page(0).lines()
}
Dart
final doc = PdfDocument.open('receipt.pdf');
final words = doc.extractWords(0); // adaptive defaults
final lines = doc.extractTextLines(0);
R
doc <- pdf_open("receipt.pdf")
words <- pdf_extract_words(doc, 0) # adaptive defaults
lines <- pdf_extract_text_lines(doc, 0)
Julia
doc = open_document("receipt.pdf")
words = extract_words(doc, 0) # adaptive defaults
lines = extract_text_lines(doc, 0)
Zig
var doc = try pdf_oxide.Document.open("receipt.pdf");
const words = try doc.extractWords(a, 0); // adaptive defaults
const lines = try doc.extractTextLines(a, 0);
Scala
Using.resource(PdfDocument.open("receipt.pdf")) { doc =>
val words = doc.page(0).wordsSeq // adaptive defaults
val lines = doc.page(0).linesSeq
}
Clojure
(with-open [doc (pdf/open "receipt.pdf")]
(pdf/words (pdf/page doc 0)) ; adaptive defaults
(pdf/lines (pdf/page doc 0)))
Objective-C
POXDocument *doc = [POXDocument openPath:@"receipt.pdf" error:&err];
NSArray<POXWord*> *words = [doc extractWords:0 error:&err]; // adaptive defaults
NSArray<POXTextLine*> *lines = [doc extractTextLines:0 error:&err];
Elixir
{:ok, doc} = PdfOxide.open("receipt.pdf")
{:ok, words} = PdfOxide.extract_words(doc, 0) # adaptive defaults
{:ok, lines} = PdfOxide.extract_text_lines(doc, 0)
Exemplo rápido
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
text = doc.extract_text(0)
print(text)
Node.js
const { PdfDocument } = require("pdf-oxide");
const doc = new PdfDocument("report.pdf");
const text = doc.extractText(0);
console.log(text);
Go
import pdfoxide "github.com/yfedoseev/pdf_oxide/go"
doc, _ := pdfoxide.Open("report.pdf")
defer doc.Close()
text, _ := doc.ExtractText(0)
fmt.Println(text)
C#
using PdfOxide.Core;
using var doc = PdfDocument.Open("report.pdf");
string text = doc.ExtractText(0);
Console.WriteLine(text);
WASM
const doc = new WasmPdfDocument(bytes);
const text = doc.extractText(0);
console.log(text);
Rust
use pdf_oxide::PdfDocument;
let mut doc = PdfDocument::open("report.pdf")?;
let text = doc.extract_text(0)?;
println!("{}", text);
Java
import fyi.oxide.pdf.*;
import java.nio.file.Path;
try (PdfDocument doc = PdfDocument.open(Path.of("report.pdf"))) {
String text = doc.extractText(0);
System.out.println(text);
}
PHP
use PdfOxide\PdfDocument;
$doc = PdfDocument::open('report.pdf');
$text = $doc->extractText(0);
echo $text;
$doc->close();
Ruby
require 'pdf_oxide'
PdfOxide::PdfDocument.open('report.pdf') do |doc|
text = doc.extract_text(0)
puts text
end
C++
#include <pdf_oxide/pdf_oxide.hpp>
auto doc = pdf_oxide::Document::open("report.pdf");
auto text = doc.extract_text(0);
std::cout << text << "\n";
Swift
import PdfOxide
let doc = try Document.open("report.pdf")
let text = try doc.extractText(0)
print(text)
Kotlin
import fyi.oxide.pdf.*
PdfDocument.open(java.nio.file.Path.of("report.pdf")).use { doc ->
val text = doc.extractText(0)
println(text)
}
Dart
import 'package:pdf_oxide/pdf_oxide.dart';
final doc = PdfDocument.open('report.pdf');
final text = doc.extractText(0);
print(text);
R
library(pdfoxide)
doc <- pdf_open("report.pdf")
text <- pdf_extract_text(doc, 0)
cat(text)
Julia
using PdfOxide
doc = open_document("report.pdf")
text = extract_text(doc, 0)
println(text)
Zig
const pdf_oxide = @import("pdf_oxide");
var doc = try pdf_oxide.Document.open("report.pdf");
const text = try doc.extractText(a, 0);
std.debug.print("{s}\n", .{text});
Scala
import fyi.oxide.pdf.PdfDocument
import scala.util.Using
Using.resource(PdfDocument.open("report.pdf")) { doc =>
val text = doc.extractText(0)
println(text)
}
Clojure
(require '[pdf-oxide.core :as pdf])
(with-open [doc (pdf/open "report.pdf")]
(println (pdf/extract-text doc 0)))
Objective-C
#import "POXPdfOxide.h"
NSError *err = nil;
POXDocument *doc = [POXDocument openPath:@"report.pdf" error:&err];
NSString *text = [doc extractText:0 error:&err];
NSLog(@"%@", text);
Elixir
{:ok, doc} = PdfOxide.open("report.pdf")
{:ok, text} = PdfOxide.extract_text(doc, 0)
IO.puts(text)
Referência da API
extract_text(page_index) -> str
Extrai todo o texto de uma página como uma única string. Detecta automaticamente PDFs com tags e usa a árvore de estrutura para a ordem de leitura quando disponível. Insere quebras de linha e espaços com base nos espaços verticais e horizontais entre os spans.
| Parâmetro | Tipo | Descrição |
|---|---|---|
page_index |
int / usize |
Índice de página baseado em zero |
Retorna: O conteúdo textual completo da página.
Python
doc = PdfDocument("report.pdf")
for i in range(doc.page_count()):
text = doc.extract_text(i)
print(f"--- Page {i + 1} ---")
print(text)
Node.js
const doc = new PdfDocument("report.pdf");
for (let i = 0; i < doc.getPageCount(); i++) {
const text = doc.extractText(i);
console.log(`--- Page ${i + 1} ---`);
console.log(text);
}
Go
doc, _ := pdfoxide.Open("report.pdf")
defer doc.Close()
count, _ := doc.PageCount()
for i := 0; i < count; i++ {
text, _ := doc.ExtractText(i)
fmt.Printf("--- Page %d ---\n", i+1)
fmt.Println(text)
}
C#
using var doc = PdfDocument.Open("report.pdf");
for (int i = 0; i < doc.PageCount; i++)
{
string text = doc.ExtractText(i);
Console.WriteLine($"--- Page {i + 1} ---");
Console.WriteLine(text);
}
WASM
const doc = new WasmPdfDocument(bytes);
for (let i = 0; i < doc.pageCount(); i++) {
const text = doc.extractText(i);
console.log(`--- Page ${i + 1} ---`);
console.log(text);
}
Rust
let mut doc = PdfDocument::open("report.pdf")?;
let page_count = doc.page_count()?;
for i in 0..page_count {
let text = doc.extract_text(i)?;
println!("--- Page {} ---", i + 1);
println!("{}", text);
}
Java
try (PdfDocument doc = PdfDocument.open(Path.of("report.pdf"))) {
int n = doc.pageCount();
for (int i = 0; i < n; i++) {
System.out.println("--- Page " + (i + 1) + " ---");
System.out.println(doc.extractText(i));
}
}
PHP
$doc = PdfDocument::open('report.pdf');
$n = $doc->pageCount();
for ($i = 0; $i < $n; $i++) {
echo "--- Page " . ($i + 1) . " ---\n";
echo $doc->extractText($i);
}
$doc->close();
Ruby
PdfOxide::PdfDocument.open('report.pdf') do |doc|
(0...doc.page_count).each do |i|
puts "--- Page #{i + 1} ---"
puts doc.extract_text(i)
end
end
C++
auto doc = pdf_oxide::Document::open("report.pdf");
int n = doc.page_count();
for (int i = 0; i < n; i++) {
std::cout << "--- Page " << (i + 1) << " ---\n";
std::cout << doc.extract_text(i) << "\n";
}
Swift
let doc = try Document.open("report.pdf")
let n = try doc.pageCount()
for i in 0..<n {
print("--- Page \(i + 1) ---")
print(try doc.extractText(i))
}
Kotlin
PdfDocument.open(java.nio.file.Path.of("report.pdf")).use { doc ->
for (i in 0 until doc.pageCount()) {
println("--- Page ${i + 1} ---")
println(doc.extractText(i))
}
}
Dart
final doc = PdfDocument.open('report.pdf');
for (var i = 0; i < doc.pageCount; i++) {
print('--- Page ${i + 1} ---');
print(doc.extractText(i));
}
R
doc <- pdf_open("report.pdf")
for (i in seq_len(pdf_page_count(doc)) - 1) {
cat(sprintf("--- Page %d ---\n", i + 1))
cat(pdf_extract_text(doc, i))
}
Julia
doc = open_document("report.pdf")
for i in 0:(page_count(doc) - 1)
println("--- Page $(i + 1) ---")
println(extract_text(doc, i))
end
Zig
var doc = try pdf_oxide.Document.open("report.pdf");
const n = try doc.pageCount();
var i: usize = 0;
while (i < n) : (i += 1) {
std.debug.print("--- Page {d} ---\n", .{i + 1});
const text = try doc.extractText(a, i);
std.debug.print("{s}\n", .{text});
}
Scala
Using.resource(PdfDocument.open("report.pdf")) { doc =>
for (i <- 0 until doc.pageCount()) {
println(s"--- Page ${i + 1} ---")
println(doc.extractText(i))
}
}
Clojure
(with-open [doc (pdf/open "report.pdf")]
(doseq [i (range (pdf/page-count doc))]
(println (str "--- Page " (inc i) " ---"))
(println (pdf/extract-text doc i))))
Objective-C
POXDocument *doc = [POXDocument openPath:@"report.pdf" error:&err];
NSInteger n = [doc pageCountError:&err];
for (NSInteger i = 0; i < n; i++) {
NSLog(@"--- Page %ld ---", (long)(i + 1));
NSLog(@"%@", [doc extractText:i error:&err]);
}
Elixir
{:ok, doc} = PdfOxide.open("report.pdf")
{:ok, n} = PdfOxide.page_count(doc)
Enum.each(0..(n - 1), fn i ->
IO.puts("--- Page #{i + 1} ---")
{:ok, text} = PdfOxide.extract_text(doc, i)
IO.puts(text)
end)
extract_spans(page_index) -> list[TextSpan]
Extrai texto como spans — trechos contínuos de texto com a mesma fonte e estilo. Cada span inclui o conteúdo de texto, caixa delimitadora, nome da fonte, tamanho da fonte, peso, flag de itálico e cor. Esta é a abordagem recomendada para a maioria das tarefas de extração que precisam de informações de layout ou fonte.
| Parâmetro | Tipo | Descrição |
|---|---|---|
page_index |
int / usize |
Índice de página baseado em zero |
Retorna: Uma lista/vetor de objetos TextSpan.
Campos do TextSpan
| Campo | Tipo | Descrição |
|---|---|---|
text |
str |
O conteúdo textual do span |
bbox |
Rect |
Caixa delimitadora (x, y, largura, altura) |
font_name |
str |
Nome/família da fonte (ex.: “Helvetica”, “TimesNewRoman”) |
font_size |
f32 |
Tamanho da fonte em pontos |
font_weight |
FontWeight |
Peso: Normal, Bold, Light, SemiBold, etc. |
is_italic |
bool |
Se o span está em itálico |
color |
Color |
Cor RGB (r, g, b) com valores de 0,0 a 1,0 |
mcid |
Option<u32> |
ID de conteúdo marcado para PDFs com tags |
sequence |
usize |
Ordem de extração (desempate na ordenação por coordenada Y) |
is_monospace |
bool |
Se a fonte é de largura fixa (Courier, Consolas, etc.) |
char_widths |
list[float] |
Larguras de avanço por glifo para caixas delimitadoras precisas |
char_spacing |
f32 |
Espaçamento entre caracteres (parâmetro Tc) |
word_spacing |
f32 |
Espaçamento entre palavras (parâmetro Tw) |
horizontal_scaling |
f32 |
Percentual de escala horizontal (Tz, padrão 100,0) |
Rust
let mut doc = PdfDocument::open("paper.pdf")?;
let spans = doc.extract_spans(0)?;
for span in &spans {
println!(
"'{}' at ({:.1}, {:.1}) font={} size={:.1}pt bold={} italic={}",
span.text,
span.bbox.x, span.bbox.y,
span.font_name,
span.font_size,
span.font_weight == FontWeight::Bold,
span.is_italic,
);
}
extract_spans_with_config(page_index, config) -> Vec<TextSpan>
Extrai spans com configuração customizada de mesclagem. Use este método quando o comportamento de mesclagem padrão produzir limites de palavras incorretos para o seu documento.
| Parâmetro | Tipo | Descrição |
|---|---|---|
page_index |
usize |
Índice de página baseado em zero |
config |
SpanMergingConfig |
Configuração dos parâmetros de extração |
Rust
use pdf_oxide::extractors::SpanMergingConfig;
let mut doc = PdfDocument::open("report.pdf")?;
let config = SpanMergingConfig::adaptive();
let spans = doc.extract_spans_with_config(0, config)?;
extract_chars(page_index) -> list[TextChar]
Extrai caracteres individuais com caixas delimitadoras precisas, metadados de fonte e propriedades de transformação. Esta é uma API de baixo nível — prefira extract_text() ou extract_spans() para a maioria dos casos de uso. A extração de caracteres é 30–50% mais rápida do que a extração de spans porque ignora o agrupamento e a mesclagem de texto.
| Parâmetro | Tipo | Descrição |
|---|---|---|
page_index |
int / usize |
Índice de página baseado em zero |
Retorna: Uma lista/vetor de objetos TextChar.
Campos do TextChar
| Campo | Tipo | Descrição |
|---|---|---|
char |
char |
O caractere |
bbox |
Rect |
Caixa delimitadora (x, y, largura, altura) |
font_name |
str |
Nome/família da fonte |
font_size |
f32 |
Tamanho da fonte em pontos |
font_weight |
FontWeight |
Peso (Normal, Bold, etc.) |
is_italic |
bool |
Flag de itálico |
color |
Color |
Cor RGB (0,0 a 1,0 por componente) |
mcid |
Option<u32> |
ID de conteúdo marcado |
origin_x |
f32 |
Coordenada X da origem da linha de base |
origin_y |
f32 |
Coordenada Y da origem da linha de base |
rotation_degrees |
f32 |
Ângulo de rotação do texto (0 a 360, no sentido horário) |
advance_width |
f32 |
Distância horizontal até a próxima posição de caractere |
matrix |
[f32; 6] |
Matriz de transformação completa [a, b, c, d, e, f] |
Python
doc = PdfDocument("report.pdf")
chars = doc.extract_chars(0)
for ch in chars:
print(f"'{ch.char}' at ({ch.bbox[0]:.1f}, {ch.bbox[1]:.1f}) "
f"font={ch.font_name} size={ch.font_size:.1f}")
<!-- Node.js: extractChars not yet in binding (js/src/index.ts) -->
Go
doc, _ := pdfoxide.Open("report.pdf")
defer doc.Close()
chars, _ := doc.ExtractChars(0)
for _, ch := range chars {
fmt.Printf("'%c' at (%.1f, %.1f) font=%s size=%.1f\n",
ch.Char, ch.X, ch.Y, ch.FontName, ch.FontSize)
}
C#
using var doc = PdfDocument.Open("report.pdf");
var chars = doc.ExtractChars(0);
foreach (var ch in chars)
{
Console.WriteLine($"'{ch.Char}' at ({ch.X:F1}, {ch.Y:F1}) {ch.W:F1}x{ch.H:F1}");
}
WASM
const doc = new WasmPdfDocument(bytes);
const chars = doc.extractChars(0);
for (const ch of chars) {
console.log(`'${ch.char}' at (${ch.bbox[0].toFixed(1)}, ${ch.bbox[1].toFixed(1)}) font=${ch.fontName} size=${ch.fontSize.toFixed(1)}`);
}
Rust
let mut doc = PdfDocument::open("report.pdf")?;
let chars = doc.extract_chars(0)?;
for ch in &chars {
println!(
"'{}' origin=({:.1}, {:.1}) rotation={:.0} advance={:.1}",
ch.char, ch.origin_x, ch.origin_y,
ch.rotation_degrees, ch.advance_width,
);
}
C++
auto doc = pdf_oxide::Document::open("report.pdf");
auto chars = doc.extract_chars(0);
for (const auto& ch : chars) {
std::printf("U+%04X at (%.1f, %.1f) font=%s size=%.1f\n",
ch.character, ch.bbox.x, ch.bbox.y,
ch.font_name.c_str(), ch.font_size);
}
Swift
let doc = try Document.open("report.pdf")
let chars = try doc.extractChars(0)
for ch in chars {
let scalar = String(UnicodeScalar(ch.character)!)
print("'\(scalar)' at (\(ch.bbox.x), \(ch.bbox.y)) font=\(ch.fontName) size=\(ch.fontSize)")
}
Dart
final doc = PdfDocument.open('report.pdf');
final chars = doc.extractChars(0);
for (final ch in chars) {
final glyph = String.fromCharCode(ch.character);
print("'$glyph' at (${ch.bbox.x}, ${ch.bbox.y}) font=${ch.fontName} size=${ch.fontSize}");
}
R
doc <- pdf_open("report.pdf")
chars <- pdf_extract_chars(doc, 0)
for (ch in chars) {
cat(sprintf("U+%04X at (%.1f, %.1f) font=%s size=%.1f\n",
ch$character, ch$bbox$x, ch$bbox$y, ch$font_name, ch$font_size))
}
Julia
doc = open_document("report.pdf")
chars = extract_chars(doc, 0)
for ch in chars
glyph = Char(ch.character)
println("'$glyph' at ($(ch.bbox.x), $(ch.bbox.y)) font=$(ch.font_name) size=$(ch.font_size)")
end
Zig
var doc = try pdf_oxide.Document.open("report.pdf");
const chars = try doc.extractChars(a, 0);
for (chars) |ch| {
std.debug.print("U+{X:0>4} at ({d:.1}, {d:.1}) font={s} size={d:.1}\n",
.{ ch.character, ch.bbox.x, ch.bbox.y, ch.fontName, ch.fontSize });
}
Objective-C
POXDocument *doc = [POXDocument openPath:@"report.pdf" error:&err];
NSArray<POXChar*> *chars = [doc extractChars:0 error:&err];
for (POXChar *ch in chars) {
NSLog(@"U+%04X at (%.1f, %.1f) font=%@ size=%.1f",
ch.character, ch.bbox.x, ch.bbox.y, ch.fontName, ch.fontSize);
}
Elixir
{:ok, doc} = PdfOxide.open("report.pdf")
{:ok, chars} = PdfOxide.extract_chars(doc, 0)
Enum.each(chars, fn ch ->
glyph = <<ch.character::utf8>>
IO.puts("'#{glyph}' at (#{ch.bbox.x}, #{ch.bbox.y}) font=#{ch.font_name} size=#{ch.font_size}")
end)
extract_page_text(page_index) -> PageText
Obtém spans, caracteres e dimensões da página em uma única passagem de extração. Mais eficiente do que chamar extract_spans() + extract_chars() separadamente, pois analisa o fluxo de conteúdo da página apenas uma vez.
| Parâmetro | Tipo | Descrição |
|---|---|---|
page_index |
int / usize |
Índice de página baseado em zero |
Retorna: Um objeto PageText (dict em Python / objeto em JS) com os campos: spans, chars, page_width, page_height, text.
Python
doc = PdfDocument("report.pdf")
result = doc.extract_page_text(0)
# result is a dict with: spans, chars, page_width, page_height, text
for span in result["spans"]:
print(f"'{span.text}' font={span.font_name} size={span.font_size}")
<!-- Node.js: extractPageText not yet in binding (js/src/index.ts) --> <!-- Go: ExtractPageText not yet in binding (go/pdf_oxide.go) --> <!-- C#: ExtractPageText not yet in binding (csharp/PdfOxide/Core/PdfDocument.cs) -->
WASM
const result = doc.extractPageText(0);
// result has: spans, chars, pageWidth, pageHeight, text
for (const span of result.spans) {
console.log(`'${span.text}' font=${span.fontName} size=${span.fontSize}`);
}
Rust
let mut doc = PdfDocument::open("report.pdf")?;
let result = doc.extract_page_text(0)?;
println!("Page is {}x{} pt", result.page_width, result.page_height);
for span in &result.spans {
println!("'{}' font={} size={:.1}", span.text, span.font_name, span.font_size);
}
Ordem de leitura com consciência de colunas
Para PDFs com múltiplas colunas (artigos científicos, jornais), use a ordem de leitura com consciência de colunas para ler cada coluna separadamente, em vez de ler através das colunas:
Python
# Default: top-to-bottom (reads across columns)
spans = doc.extract_spans(0)
# Column-aware: reads each column separately
spans = doc.extract_spans(0, reading_order="column_aware")
<!-- Node.js: extractSpans not yet in binding (js/src/index.ts) --> <!-- Go: ExtractSpans not yet in binding (go/pdf_oxide.go) --> <!-- C#: ExtractSpans not yet in binding (csharp/PdfOxide/Core/PdfDocument.cs) -->
WASM
const spans = doc.extractSpans(0, undefined, "column_aware");
Rust
use pdf_oxide::extractors::ReadingOrder;
let spans = doc.extract_spans_with_reading_order(0, ReadingOrder::ColumnAware)?;
to_plain_text(page_index, options) -> str
Converte uma única página em texto simples. Aceita opções de conversão para consistência da API, embora a maioria das opções se aplique principalmente à saída em Markdown/HTML.
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
page_index |
int / usize |
– | Índice de página baseado em zero |
preserve_layout |
bool |
false |
Preservar layout visual |
detect_headings |
bool |
true |
Detectar cabeçalhos |
include_images |
bool |
true |
Incluir imagens |
image_output_dir |
str / None |
None |
Diretório de saída de imagens |
Python
doc = PdfDocument("paper.pdf")
text = doc.to_plain_text(0)
Node.js
const doc = new PdfDocument("paper.pdf");
const text = doc.toPlainText(0);
Go
doc, _ := pdfoxide.Open("paper.pdf")
defer doc.Close()
text, _ := doc.ToPlainText(0)
C#
using var doc = PdfDocument.Open("paper.pdf");
string text = doc.ToPlainText(0);
WASM
const doc = new WasmPdfDocument(bytes);
const text = doc.extractText(0);
Rust
use pdf_oxide::converters::ConversionOptions;
let mut doc = PdfDocument::open("paper.pdf")?;
let options = ConversionOptions::default();
let text = doc.to_plain_text(0, &options)?;
C++
auto doc = pdf_oxide::Document::open("paper.pdf");
auto text = doc.to_plain_text(0);
Swift
let doc = try Document.open("paper.pdf")
let text = try doc.toPlainText(0)
Dart
final doc = PdfDocument.open('paper.pdf');
final text = doc.toPlainText(0);
R
doc <- pdf_open("paper.pdf")
text <- pdf_to_plain_text(doc, 0)
Julia
doc = open_document("paper.pdf")
text = to_plain_text(doc, 0)
Zig
var doc = try pdf_oxide.Document.open("paper.pdf");
const text = try doc.toPlainText(a, 0);
Objective-C
POXDocument *doc = [POXDocument openPath:@"paper.pdf" error:&err];
NSString *text = [doc toPlainText:0 error:&err];
Elixir
{:ok, doc} = PdfOxide.open("paper.pdf")
{:ok, text} = PdfOxide.to_plain_text(doc, 0)
extract_hierarchical_content(page_index) -> Option<StructureElement>
Extrai o conteúdo da página como uma árvore de estrutura hierárquica. Retorna None para PDFs sem tags. Para PDFs com tags, retorna uma árvore StructureElement que representa a estrutura lógica do documento (títulos, parágrafos, tabelas, figuras).
| Parâmetro | Tipo | Descrição |
|---|---|---|
page_index |
int / usize |
Índice de página baseado em zero |
Rust
let mut doc = PdfDocument::open("tagged-report.pdf")?;
if let Some(root) = doc.extract_hierarchical_content(0)? {
println!("Structure type: {:?}", root.structure_type);
for child in &root.children {
println!(" Child: {:?}", child.structure_type);
}
}
Exemplos avançados
Construir uma tabela de frequência de palavras a partir de spans
from collections import Counter
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
words = Counter()
for page in range(doc.page_count()):
text = doc.extract_text(page)
for word in text.split():
words[word.lower().strip(".,;:!?\"'()[]")] += 1
for word, count in words.most_common(20):
print(f"{word:20s} {count}")
Detectar títulos em negrito usando metadados de spans
use pdf_oxide::PdfDocument;
use pdf_oxide::layout::FontWeight;
let mut doc = PdfDocument::open("paper.pdf")?;
let spans = doc.extract_spans(0)?;
let headings: Vec<_> = spans.iter()
.filter(|s| s.font_weight == FontWeight::Bold && s.font_size > 14.0)
.collect();
for h in headings {
println!("Heading: '{}' ({}pt)", h.text, h.font_size);
}
Exportar dados por caractere para CSV
import csv
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
chars = doc.extract_chars(0)
with open("characters.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["char", "x", "y", "width", "height", "font", "size"])
for ch in chars:
writer.writerow([
ch.char, ch.bbox[0], ch.bbox[1],
ch.bbox[2], ch.bbox[3],
ch.font_name, ch.font_size,
])
Extrair caminhos vetoriais
extract_paths() retorna dados de caminhos vetoriais (linhas, curvas, retângulos) de uma página. Útil para detectar bordas de tabelas, separadores e elementos gráficos.
doc = PdfDocument("report.pdf")
paths = doc.extract_paths(0)
for path in paths:
for op in path["operations"]:
print(f"{op['type']}: {op.get('x', '')}, {op.get('y', '')}")
# types: move_to, line_to, curve_to, rectangle, close_path
Páginas relacionadas
- Conversão para Markdown – Converter texto em Markdown estruturado
- Conversão para HTML – Converter texto em HTML com formatação
- Busca de texto – Pesquisar texto extraído com regex
- Metadados e XMP – Ler metadados do nível do documento