Textextraktion
PDF Oxide bietet mehrere Ebenen der Textextraktion: vollständiger Seitentext, stilisierte Spans mit Schriftmetadaten und einzelne Zeichen mit präziser Positionierung. Verwenden Sie extract_text() für schnellen Inhaltszugriff, extract_spans() wenn Sie Schrift- und Positionsdaten benötigen, und extract_chars() für zeichenweise Analysen wie benutzerdefinierte Layout-Engines oder OCR-Nachbearbeitung.
Für getaggte PDFs folgt die Textextraktion automatisch dem Strukturbaum des Dokuments, um die korrekte Lesereihenfolge sicherzustellen. Für ungetaggte PDFs verwendet die Extraktion die Reihenfolge des Seiteninhalts mit intelligenter Zeilenerkennung — einschließlich eines Einspaltenschutzes, der die Fragmentierung von Fließtext in RFC- und Dissertationsdokumenten verhindert.
Unterstützung der Lesereihenfolge
Die Lesereihenfolgen-Pipeline liefert korrekte Ausgaben für verschiedene Schriftsysteme und Layouts:
- Latin — Standard-Links-nach-rechts, oben-nach-unten mit Spaltenerkennung.
- Arabic — Umkehrung vorgeformter Spans (Pass 0) ordnet Zeichen in logischer Lesereihenfolge statt visueller Reihenfolge an.
- CJK — Der räumliche Tabellendetektor erhält Spalten mit Rowspan-Beschriftungen; 3-Punkt-Y-Band-Quantisierung verhindert das Vermischen von Tabelleninhalt mit Fließtext.
- Gedrehte / dvips-generierte PDFs — Medianbasierte Ausreißerentfernung bei der Spaltenerkennung behandelt degenerierte CTM-Koordinaten.
- Mehrspaltige wissenschaftliche Artikel — XYCut-Einspaltenschutz behebt Fragmentierung; zeilenbewusste Span-Sortierung behandelt Tabelleninhalt in Textblöcken.
Wort- und Zeilensegmentierung
extract_words() und extract_text_lines() akzeptieren optionale Schlüsselwortargumente zur Anpassung der Wort- und Zeilenumbruchschwellenwerte:
| Parameter | Standard | Beschreibung |
|---|---|---|
word_gap_threshold |
adaptiv | Minimaler horizontaler Abstand (in Punkten) zwischen benachbarten Zeichen, der als Wortgrenze gilt |
line_gap_threshold |
adaptiv | Minimaler vertikaler Abstand zwischen Grundlinien, der als Zeilenumbruch gilt |
profile |
"auto" |
Eines von "auto", "dense", "standard", "sparse" — wählt eine für verschiedene Layouts optimierte Voreinstellung |
Adaptive Parameter werden aus den Schriftmetriken der Seite abgeleitet. Verwenden Sie page_layout_params() zur Inspektion der berechneten Werte und ExtractionProfile zum Erstellen eines eigenen Profils.
Nur Python-Feinabstimmung:
word_gap_threshold,line_gap_threshold,profileundpage_layout_params()sind im Python-Binding verfügbar. Die Node.js-, JavaScript-, Go-, C#- und WASM-Bindings stellenextractWords(pageIndex)/extractTextLines(pageIndex)mit adaptiven Standardwerten ohne kwargs bereit. Für die Feinabstimmung aus diesen Sprachen verwenden Sie bitte die Rust-API unten.
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)
Schnellbeispiel
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)
API-Referenz
extract_text(page_index) -> str
Extrahiert den gesamten Text einer Seite als einzelne Zeichenkette. Erkennt automatisch getaggte PDFs und verwendet den Strukturbaum für die Lesereihenfolge, sofern verfügbar. Fügt Zeilenumbrüche und Leerzeichen basierend auf vertikalen und horizontalen Abständen zwischen Spans ein.
| Parameter | Typ | Beschreibung |
|---|---|---|
page_index |
int / usize |
Nullbasierter Seitenindex |
Rückgabe: Der vollständige Textinhalt der Seite.
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]
Extrahiert Text als Spans — zusammenhängende Textabschnitte mit gleicher Schrift und gleichem Stil. Jeder Span enthält den Textinhalt, das Begrenzungsrechteck, den Schriftnamen, die Schriftgröße, das Schriftgewicht, ein Kursiv-Flag und die Farbe. Dies ist der empfohlene Ansatz für die meisten Extraktionsaufgaben, die Layout- oder Schriftinformationen benötigen.
| Parameter | Typ | Beschreibung |
|---|---|---|
page_index |
int / usize |
Nullbasierter Seitenindex |
Rückgabe: Eine Liste/ein Vektor von TextSpan-Objekten.
TextSpan-Felder
| Feld | Typ | Beschreibung |
|---|---|---|
text |
str |
Der Textinhalt des Spans |
bbox |
Rect |
Begrenzungsrechteck (x, y, Breite, Höhe) |
font_name |
str |
Schriftname/-familie (z. B. “Helvetica”, “TimesNewRoman”) |
font_size |
f32 |
Schriftgröße in Punkten |
font_weight |
FontWeight |
Schriftgewicht: Normal, Bold, Light, SemiBold usw. |
is_italic |
bool |
Ob der Span kursiv ist |
color |
Color |
RGB-Farbe (r, g, b) mit Werten von 0,0 bis 1,0 |
mcid |
Option<u32> |
Marked-Content-ID für getaggte PDFs |
sequence |
usize |
Extraktionsreihenfolge (Tiebreaker bei Y-Koordinaten-Sortierung) |
is_monospace |
bool |
Ob die Schrift nichtproportional ist (Courier, Consolas usw.) |
char_widths |
list[float] |
Vorschubbreiten pro Glyphe für genaue Begrenzungsrechtecke |
char_spacing |
f32 |
Zeichenabstand (Tc-Parameter) |
word_spacing |
f32 |
Wortabstand (Tw-Parameter) |
horizontal_scaling |
f32 |
Horizontale Skalierung in Prozent (Tz, Standard 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>
Extrahiert Spans mit benutzerdefinierter Span-Zusammenführungskonfiguration. Verwenden Sie diese Methode, wenn das standardmäßige Zusammenführungsverhalten für Ihr Dokument falsche Wortgrenzen erzeugt.
| Parameter | Typ | Beschreibung |
|---|---|---|
page_index |
usize |
Nullbasierter Seitenindex |
config |
SpanMergingConfig |
Konfiguration zur Steuerung der Extraktionsparameter |
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]
Extrahiert einzelne Zeichen mit präzisen Begrenzungsrechtecken, Schriftmetadaten und Transformationseigenschaften. Dies ist eine Low-Level-API — bevorzugen Sie für die meisten Anwendungsfälle extract_text() oder extract_spans(). Die Zeichenextraktion ist 30–50% schneller als die Span-Extraktion, da das Gruppieren und Zusammenführen von Text übersprungen wird.
| Parameter | Typ | Beschreibung |
|---|---|---|
page_index |
int / usize |
Nullbasierter Seitenindex |
Rückgabe: Eine Liste/ein Vektor von TextChar-Objekten.
TextChar-Felder
| Feld | Typ | Beschreibung |
|---|---|---|
char |
char |
Das Zeichen |
bbox |
Rect |
Begrenzungsrechteck (x, y, Breite, Höhe) |
font_name |
str |
Schriftname/-familie |
font_size |
f32 |
Schriftgröße in Punkten |
font_weight |
FontWeight |
Schriftgewicht (Normal, Bold usw.) |
is_italic |
bool |
Kursiv-Flag |
color |
Color |
RGB-Farbe (0,0 bis 1,0 pro Komponente) |
mcid |
Option<u32> |
Marked-Content-ID |
origin_x |
f32 |
X-Koordinate des Grundlinienursprungs |
origin_y |
f32 |
Y-Koordinate des Grundlinienursprungs |
rotation_degrees |
f32 |
Textrotationswinkel (0–360, im Uhrzeigersinn) |
advance_width |
f32 |
Horizontaler Abstand zur nächsten Zeichenposition |
matrix |
[f32; 6] |
Vollständige Transformationsmatrix [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
Ruft Spans, Zeichen und Seitenabmessungen in einem einzigen Extraktionsdurchlauf ab. Effizienter als getrennte Aufrufe von extract_spans() + extract_chars(), da der Seiteninhaltsstrom nur einmal geparst wird.
| Parameter | Typ | Beschreibung |
|---|---|---|
page_index |
int / usize |
Nullbasierter Seitenindex |
Rückgabe: Ein PageText-Objekt (Python-Dict / JS-Objekt) mit den Feldern: 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);
}
Spaltenbewusste Lesereihenfolge
Für mehrspaltige PDFs (wissenschaftliche Artikel, Zeitungen) verwenden Sie die spaltenbewusste Lesereihenfolge, um jede Spalte einzeln zu lesen, anstatt spaltenübergreifend zu lesen:
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
Konvertiert eine einzelne Seite in einfachen Text. Akzeptiert Konvertierungsoptionen für API-Konsistenz, obwohl die meisten Optionen hauptsächlich für Markdown-/HTML-Ausgaben gelten.
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
page_index |
int / usize |
– | Nullbasierter Seitenindex |
preserve_layout |
bool |
false |
Visuelles Layout erhalten |
detect_headings |
bool |
true |
Überschriften erkennen |
include_images |
bool |
true |
Bilder einschließen |
image_output_dir |
str / None |
None |
Ausgabeverzeichnis für Bilder |
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>
Extrahiert den Seiteninhalt als hierarchischen Strukturbaum. Gibt None für ungetaggte PDFs zurück. Für getaggte PDFs wird ein StructureElement-Baum zurückgegeben, der die logische Struktur des Dokuments darstellt (Überschriften, Absätze, Tabellen, Abbildungen).
| Parameter | Typ | Beschreibung |
|---|---|---|
page_index |
int / usize |
Nullbasierter Seitenindex |
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);
}
}
Erweiterte Beispiele
Worthäufigkeitstabelle aus Spans erstellen
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}")
Fette Überschriften anhand von Span-Metadaten erkennen
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);
}
Zeichenweise Daten als CSV exportieren
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,
])
Vektorpfade extrahieren
extract_paths() gibt Vektorpfaddaten (Linien, Kurven, Rechtecke) einer Seite zurück. Nützlich zum Erkennen von Tabellenrahmen, Trennlinien und grafischen Elementen.
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
Verwandte Seiten
- Markdown-Konvertierung – Text in strukturiertes Markdown umwandeln
- HTML-Konvertierung – Text in HTML mit Formatierung umwandeln
- Textsuche – Extrahierten Text mit Regex durchsuchen
- Metadaten und XMP – Metadaten auf Dokumentebene lesen