Bereichsextraktion — Inhalte aus einem bestimmten Bereich abrufen
Bei der Verarbeitung von Rechnungen, Kontoauszügen, Steuerformularen oder beliebigen Template-Layouts wissen Sie meistens bereits, wo sich die Felder befinden. Statt die gesamte Seite zu extrahieren und nach dem Wert zu suchen, weisen Sie PDF Oxide einfach auf das exakte Rechteck hin und erhalten nur das, was dort steht.
Die fluente within(page, rect)-API gibt einen Bereich mit eingeschränktem Geltungsbereich zurück, auf dem Sie Extraktionsmethoden verketten können: extract_text(), extract_words(), extract_chars(), extract_tables().
Binding-Abdeckung.
within(page, rect)ist in Python, Rust und WASM verfügbar. Go und C# bieten gleichwertige Low-Level-Hilfsfunktionen (ExtractTextInRect,ExtractWordsInRect,ExtractImagesInRect) — siehe unten. Die vollständige in-rect-Familie (Text, Wörter, Zeilen, Tabellen, Bilder) ist in Rust, dem C ABI und dem Swift-Wrapper vollständig verfügbar; welches Binding was unterstützt, entnehmen Sie Varianten der in-rect-Extraktion.
Schnellbeispiel
rect ist (x, y, width, height) in PDF-Punkten, mit dem Ursprung an der linken unteren Ecke der Seite. Letter-Seiten sind 612 × 792 Punkte groß.
Python
from pdf_oxide import PdfDocument
doc = PdfDocument("invoice.pdf")
# Top 92 points of page 0 — typical header band
header = doc.within(0, (0, 700, 612, 92)).extract_text()
print(header)
Rust
use pdf_oxide::PdfDocument;
use pdf_oxide::geometry::Rect;
let mut doc = PdfDocument::open("invoice.pdf")?;
let header = doc.within(0, Rect::new(0.0, 700.0, 612.0, 92.0)).extract_text()?;
println!("{}", header);
JavaScript (WASM)
import { WasmPdfDocument } from "pdf-oxide-wasm";
const doc = new WasmPdfDocument(bytes);
const headerRegion = doc.within(0, [0, 700, 612, 92]);
console.log(headerRegion.extractText());
doc.free();
Go (Low-Level-Hilfsfunktion, gleicher Effekt)
package main
import (
"fmt"
"log"
pdfoxide "github.com/yfedoseev/pdf_oxide/go"
)
func main() {
doc, err := pdfoxide.Open("invoice.pdf")
if err != nil { log.Fatal(err) }
defer doc.Close()
// ExtractTextInRect(pageIndex, x, y, width, height)
header, _ := doc.ExtractTextInRect(0, 0, 700, 612, 92)
fmt.Println(header)
}
C# (Low-Level-Hilfsfunktion)
using PdfOxide;
using var doc = PdfDocument.Open("invoice.pdf");
string header = doc.ExtractTextInRect(0, 0, 700, 612, 92);
Console.WriteLine(header);
Java (page.text(region); BBox im Eckpunkt-Format (x0, y0, x1, y1))
import fyi.oxide.pdf.PdfDocument;
import fyi.oxide.pdf.geometry.BBox;
try (PdfDocument doc = PdfDocument.open(java.nio.file.Path.of("invoice.pdf"))) {
// Top 92 points of page 0 → corners (0, 700) … (612, 792)
String header = doc.page(0).text(new BBox(0, 700, 612, 792));
System.out.println(header);
}
Kotlin
import fyi.oxide.pdf.PdfDocument
import fyi.oxide.pdf.geometry.BBox
PdfDocument.open(java.nio.file.Path.of("invoice.pdf")).use { doc ->
val header = doc.page(0).text(BBox(0.0, 700.0, 612.0, 792.0))
println(header)
}
Scala
import fyi.oxide.pdf.PdfDocument
import fyi.oxide.pdf.geometry.BBox
import scala.util.Using
Using.resource(PdfDocument.open("invoice.pdf")) { doc =>
val header = doc.page(0).text(BBox(0, 700, 612, 792))
println(header)
}
Clojure
(require '[pdf-oxide.core :as pdf])
(import '[fyi.oxide.pdf.geometry BBox])
(with-open [doc (pdf/open "invoice.pdf")]
;; Top 92 points of page 0 → corners (0 700) … (612 792)
(println (pdf/page-text (pdf/page doc 0) (BBox. 0 700 612 792))))
C++
#include <pdf_oxide/pdf_oxide.hpp>
auto doc = pdf_oxide::Document::open("invoice.pdf");
// extract_text_in_rect(page, x, y, w, h)
auto header = doc.extract_text_in_rect(0, 0, 700, 612, 92);
std::cout << header << "\n";
Swift
import PdfOxide
let doc = try Document.open("invoice.pdf")
let header = try doc.extractTextInRect(0, x: 0, y: 700, w: 612, h: 92)
print(header)
Dart
import 'package:pdf_oxide/pdf_oxide.dart';
final doc = PdfDocument.open('invoice.pdf');
final header = doc.extractTextInRect(0, 0, 700, 612, 92);
print(header);
doc.close();
R
library(pdfoxide)
doc <- pdf_open("invoice.pdf")
# pdf_extract_text_in_rect(doc, page, x, y, width, height)
header <- pdf_extract_text_in_rect(doc, 0, 0, 700, 612, 92)
cat(header)
Julia
using PdfOxide
doc = open_document("invoice.pdf")
header = extract_text_in_rect(doc, 0, 0, 700, 612, 92)
println(header)
Zig
const pdf_oxide = @import("pdf_oxide");
const a = std.heap.page_allocator;
var doc = try pdf_oxide.Document.open("invoice.pdf");
const header = try doc.extractTextInRect(a, 0, 0, 700, 612, 92); // free header
std.debug.print("{s}\n", .{header});
Objective-C
#import "POXPdfOxide.h"
NSError *err = nil;
POXDocument *doc = [POXDocument openPath:@"invoice.pdf" error:&err];
NSString *header = [doc extractTextInRect:0 x:0 y:700 w:612 h:92 error:&err];
NSLog(@"%@", header);
Elixir
{:ok, doc} = PdfOxide.open("invoice.pdf")
# extract_text_in_rect(doc, page, x, y, w, h)
{:ok, header} = PdfOxide.extract_text_in_rect(doc, 0, 0, 700, 612, 92)
IO.puts(header)
Verkettete Extraktion aus einem Bereich
Die fluente within()-Form in Python / Rust / WASM ermöglicht es, beliebige Extraktionsmethoden auf demselben eingeschränkten Bereich aufzurufen, ohne das Rechteck erneut angeben zu müssen:
Python
doc = PdfDocument("invoice.pdf")
region = doc.within(0, (400, 100, 200, 200)) # bottom-right 200×200 box
total_text = region.extract_text() # plain text
words = region.extract_words() # word-level records
chars = region.extract_chars() # character-level records
Rust
let region = doc.within(0, Rect::new(400.0, 100.0, 200.0, 200.0));
let text = region.extract_text()?;
let words = region.extract_words()?;
C++ (keine fluente Verkettung — jede in-rect-Hilfsfunktion für dasselbe Rechteck einzeln aufrufen)
// bottom-right 200×200 box: x=400, y=100, w=200, h=200
auto text = doc.extract_text_in_rect(0, 400, 100, 200, 200);
auto words = doc.extract_words_in_rect(0, 400, 100, 200, 200);
auto lines = doc.extract_lines_in_rect(0, 400, 100, 200, 200);
Swift
let text = try doc.extractTextInRect(0, x: 400, y: 100, w: 200, h: 200)
let words = try doc.extractWordsInRect(0, x: 400, y: 100, w: 200, h: 200)
Dart
final text = doc.extractTextInRect(0, 400, 100, 200, 200);
final words = doc.extractWordsInRect(0, 400, 100, 200, 200);
R
text <- pdf_extract_text_in_rect(doc, 0, 400, 100, 200, 200)
words <- pdf_extract_words_in_rect(doc, 0, 400, 100, 200, 200)
Julia
text = extract_text_in_rect(doc, 0, 400, 100, 200, 200)
words = extract_words_in_rect(doc, 0, 400, 100, 200, 200)
Zig
const text = try doc.extractTextInRect(a, 0, 400, 100, 200, 200);
const words = try doc.extractWordsInRect(a, 0, 400, 100, 200, 200); // freeWords
Objective-C
NSString *text = [doc extractTextInRect:0 x:400 y:100 w:200 h:200 error:&err];
NSArray<POXWord*> *words = [doc extractWordsInRect:0 x:400 y:100 w:200 h:200 error:&err];
Elixir
{:ok, text} = PdfOxide.extract_text_in_rect(doc, 0, 400, 100, 200, 200)
{:ok, words} = PdfOxide.extract_words_in_rect(doc, 0, 400, 100, 200, 200)
Typische Anwendungsfälle
Rechnungsfelder extrahieren
Eine Rechnung enthält Lieferantenadresse, Rechnungsnummer und Positionstabelle meist in festen Zonen. Definieren Sie die Rechtecke einmal pro Template:
from pdf_oxide import PdfDocument
TEMPLATES = {
"acme_v1": {
"invoice_no": (450, 720, 120, 20),
"issue_date": (450, 700, 120, 20),
"vendor_name": ( 50, 740, 300, 40),
"total": (450, 100, 120, 24),
},
}
def parse_invoice(path, template):
doc = PdfDocument(path)
out = {}
for field, rect in template.items():
out[field] = doc.within(0, rect).extract_text().strip()
return out
print(parse_invoice("invoice-2025-04.pdf", TEMPLATES["acme_v1"]))
Kontoauszug-Buchungszeilen
Die meisten Kontoauszüge haben einen schmalen „Transaktions"-Streifen. Schneiden Sie diesen Bereich aus und rufen Sie extract_words() auf, um jede Zeile in Lesereihenfolge mit ihrem Bounding Box zu erhalten:
doc = PdfDocument("statement.pdf")
for page in range(doc.page_count()):
txn_region = doc.within(page, (36, 72, 540, 650)) # skip header + footer
for w in txn_region.extract_words():
print(f"page {page}: {w.text} at ({w.x0:.0f},{w.y0:.0f})")
Kopf- und Fußzeilen entfernen
Wenn Sie nur den Fließtext indexieren möchten, schneiden Sie den oberen und unteren Rand jeder Seite weg:
Rust
let mut doc = PdfDocument::open("book.pdf")?;
for i in 0..doc.page_count()? {
let body = doc.within(i, Rect::new(0.0, 100.0, 612.0, 600.0))
.extract_text()?;
// index `body` …
}
Tabellenbereiche erkennen
Wenn Sie wissen, dass eine Seite eine Tabelle enthält und wo sie sich befindet, begrenzen Sie den Bereich auf das Tabellenrechteck und lassen Sie extract_tables() nur auf diesen Bereich fokussieren:
Python
tables = doc.within(0, (50, 200, 500, 400)).extract_tables()
for t in tables:
for row in t["rows"]:
print([c["text"] for c in row["cells"]])
Welche Varianten der rechteckbegrenzten Extraktion gibt es? {#what-rect-scoped-extraction-variants-exist}
Über extract_text(), extract_words() und extract_chars() hinaus gibt es zwei weitere rechteckbegrenzte Varianten, die geometriebewusste Ergebnisse aus einem einzelnen Rechteck liefern: Zeilen im Rechteck und Tabellen im Rechteck. Beide filtern eine Ganzseiten-Extraktion auf die Bereiche, deren Bounding Box mit Ihrem Rechteck überschneidet, sodass die zurückgegebenen Koordinaten und die Lesereihenfolge dieselben wie bei einem Ganzseiten-Aufruf sind — nur ausgeschnitten.
Textzeilen in einem Bereich extrahieren (extract_lines_in_rect)
Gibt die Datensätze auf Zeilenebene (jeweils mit Text, Bounding Box und Wortzahl) zurück, die innerhalb des Rechtecks liegen. Verwenden Sie diese Methode, wenn Sie ganze Zeilen in Lesereihenfolge benötigen statt einzelner Wörter — z. B. Adressblöcke, mehrzeilige Summen oder eine einzelne Kontoauszugszeile.
Die C-ABI-Signatur ist die maßgebliche Referenz:
FfiTextLineList *pdf_document_extract_lines_in_rect(
PdfDocument *handle,
int32_t page_index,
float x, float y, float w, float h,
int32_t *error_code);
Rust — extract_lines_in_rect(page_index, region) -> Result<Vec<PathContent>> auf PdfDocument:
use pdf_oxide::PdfDocument;
use pdf_oxide::geometry::Rect;
let doc = PdfDocument::open("statement.pdf")?;
// Transactions band: skip the header (top 92pt) and footer (bottom 72pt)
let region = Rect::new(36.0, 72.0, 540.0, 628.0);
let lines = doc.extract_lines_in_rect(0, region)?;
for line in &lines {
println!("{:?}", line.bbox);
}
Python — der fluente Bereich stellt Zeilen über extract_text_lines() bereit:
from pdf_oxide import PdfDocument
doc = PdfDocument("statement.pdf")
# Same band as the Rust example above
region = doc.within(0, (36, 72, 540, 628))
for line in region.extract_text_lines():
print(line.text, line.bbox)
Swift — extractLinesInRect(_:x:y:w:h:) gibt [TextLine] zurück:
import PdfOxide
let doc = try PdfDocument(path: "statement.pdf")
let lines = try doc.extractLinesInRect(0, x: 36, y: 72, w: 540, h: 628)
for line in lines {
print(line.text, line.bbox, line.wordCount)
}
C++ — extract_lines_in_rect(page, x, y, w, h) gibt std::vector<TextLine> zurück:
auto lines = doc.extract_lines_in_rect(0, 36, 72, 540, 628);
for (const auto& line : lines) {
std::cout << line.text << "\n";
}
Dart — extractLinesInRect(page, x, y, w, h) gibt List<TextLine> zurück:
final lines = doc.extractLinesInRect(0, 36, 72, 540, 628);
for (final line in lines) {
print('${line.text} ${line.bbox}');
}
R — pdf_extract_lines_in_rect(doc, page, x, y, width, height):
lines <- pdf_extract_lines_in_rect(doc, 0, 36, 72, 540, 628)
Julia — extract_lines_in_rect(doc, page, x, y, w, h):
lines = extract_lines_in_rect(doc, 0, 36, 72, 540, 628)
for line in lines
println(line.text, " ", line.bbox)
end
Zig — extractLinesInRect(allocator, page, x, y, w, h):
const lines = try doc.extractLinesInRect(a, 0, 36, 72, 540, 628); // freeTextLines
Objective-C — extractLinesInRect:x:y:w:h: gibt NSArray<POXTextLine*> zurück:
NSArray<POXTextLine*> *lines = [doc extractLinesInRect:0 x:36 y:72 w:540 h:628 error:&err];
Elixir — extract_lines_in_rect(doc, page, x, y, w, h):
{:ok, lines} = PdfOxide.extract_lines_in_rect(doc, 0, 36, 72, 540, 628)
Go / C#. Der C-Einstiegspunkt
extract_lines_in_rectexistiert, wird aber von den Go- und C#-Wrappern noch nicht bereitgestellt. Extrahieren Sie in diesen Sprachen die Zeilen für die gesamte Seite und filtern Sie nach den zurückgegebenen Bounding Boxes, oder verwenden SieExtractWordsInRect(Go) und gruppieren Sie die Wörter selbst zu Zeilen.
Tabellen in einem Bereich extrahieren (extract_tables_in_rect)
Begrenzt die Tabellenerkennung auf ein einzelnes Rechteck — es werden nur Tabellen zurückgegeben, deren Bounding Box das Rechteck schneidet. Dies ist die geometriebewusste Entsprechung des oben gezeigten fluenten within(...).extract_tables().
C-ABI-Signatur:
FfiTableList *pdf_document_extract_tables_in_rect(
PdfDocument *handle,
int32_t page_index,
float x, float y, float w, float h,
int32_t *error_code);
Rust — extract_tables_in_rect(page_index, region) -> Result<Vec<Table>> (die Variante ..._with_config nimmt eine benutzerdefinierte TableDetectionConfig entgegen):
use pdf_oxide::PdfDocument;
use pdf_oxide::geometry::Rect;
let doc = PdfDocument::open("invoice.pdf")?;
let region = Rect::new(50.0, 200.0, 500.0, 400.0);
let tables = doc.extract_tables_in_rect(0, region)?;
for table in &tables {
println!("{} rows × {} cols", table.rows.len(), table.col_count);
}
Python — über den fluenten Bereich:
from pdf_oxide import PdfDocument
doc = PdfDocument("invoice.pdf")
tables = doc.within(0, (50, 200, 500, 400)).extract_tables()
for t in tables:
for row in t["rows"]:
print([c["text"] for c in row["cells"]])
Swift — extractTablesInRect(_:x:y:w:h:) gibt [Table] zurück:
let tables = try doc.extractTablesInRect(0, x: 50, y: 200, w: 500, h: 400)
for table in tables {
print("\(table.rowCount) rows, header: \(table.hasHeader)")
}
C++ — extract_tables_in_rect(page, x, y, w, h) gibt std::vector<Table> zurück:
auto tables = doc.extract_tables_in_rect(0, 50, 200, 500, 400);
for (const auto& table : tables) {
std::cout << table.rows.size() << " rows\n";
}
Dart — extractTablesInRect(page, x, y, w, h) gibt List<Table> zurück:
final tables = doc.extractTablesInRect(0, 50, 200, 500, 400);
for (final table in tables) {
print('${table.rows.length} rows');
}
R — pdf_extract_tables_in_rect(doc, page, x, y, width, height):
tables <- pdf_extract_tables_in_rect(doc, 0, 50, 200, 500, 400)
Julia — extract_tables_in_rect(doc, page, x, y, w, h):
tables = extract_tables_in_rect(doc, 0, 50, 200, 500, 400)
Zig — extractTablesInRect(allocator, page, x, y, w, h):
const tables = try doc.extractTablesInRect(a, 0, 50, 200, 500, 400);
Objective-C — extractTablesInRect:x:y:w:h: gibt NSArray<POXTable*> zurück:
NSArray<POXTable*> *tables = [doc extractTablesInRect:0 x:50 y:200 w:500 h:400 error:&err];
Elixir — extract_tables_in_rect(doc, page, x, y, w, h):
{:ok, tables} = PdfOxide.extract_tables_in_rect(doc, 0, 50, 200, 500, 400)
Go / C#. Wie bei den Zeilen existiert der C-Einstiegspunkt
extract_tables_in_rect, ist aber in Go oder C# noch nicht eingebunden. Rufen SieExtractTables(page)für die gesamte Seite auf und behalten Sie nur die Tabellen, deren Bounding Box in Ihr Rechteck fällt.
Wie extrahiere ich eine Seite automatisch, ohne Text oder OCR zu wählen?
Wenn Sie nicht wissen, ob eine Seite digitalen Text, einen Scan oder eine Mischung enthält, übernimmt extract_page_auto das Routing. Es führt den AutoExtractor aus — bereichsweises Text-vs.-OCR-Routing mit elegantem nativem Fallback (ohne undurchsichtige OCR-Fehler) — und gibt ein JSON-PageExtraction zurück: einen Seiten-kind, den in Lesereihenfolge zusammengestellten text, eine confidence, einen typisierten reason, ein ocr_used-Flag und ein regions[]-Array, in dem jeder Bereich bbox, kind, text, confidence, source und reason trägt (bbox und reason sind auch dann vorhanden, wenn der Text eines Bereichs leer ist, damit die Lesereihenfolge nie stillschweigend beschädigt wird).
Es ist {}-tolerant: Übergeben Sie ein leeres/null Options-JSON für die Standardwerte oder ein AutoExtractOptions-Objekt. Die erkannten Felder (serialisiert als snake_case) sind:
| Feld | Typ | Standard | Bedeutung |
|---|---|---|---|
mode |
"text_only" | "auto" | "force_ocr" |
"auto" |
Text-vs.-OCR-Routing-Strategie |
reconstruct_image_tables |
bool | true |
Nur-Bild-Tabellen über den räumlichen Detektor auf OCR-Spans neu aufbauen |
emit_placeholders |
bool | true |
Positionierte Figure/Table-Platzhalter in den Textfluss einfügen |
ocr_languages |
string[] | [] |
OCR-Sprachhinweise (z. B. ["english","chinese"]) |
min_text_confidence |
float | null | null |
Konfidenz-Schwellenwert für die automatische Entscheidung |
table_confidence |
float | null | null |
Schwellenwert für die Bild-Tabellen-Rekonstruktion |
force_ocr_pages |
int[] | [] |
0-basierte Seitenindizes, für die OCR erzwungen wird |
OCR-Feature-Gate. OCR läuft tatsächlich nur, wenn die Bibliothek mit der Feature
ocrgebaut wurde; andernfalls fälltextract_page_autoauf die native Textschicht zurück (kein Fehler). Der automatische Einstiegspunkt ist in Python, Go, C#, Swift, WASM und dem C ABI verfügbar. In Rust ist es die Bibliotheks-APIAutoExtractorstatt einer einzeiligenPdfDocument-Methode — siehe unten.
Python — extract_page_auto(page, options_json=None) -> str (JSON):
import json
from pdf_oxide import PdfDocument
doc = PdfDocument("mixed-scan.pdf")
# Defaults (balanced preset)
page = json.loads(doc.extract_page_auto(0))
print(page["kind"], page["confidence"], page["ocr_used"])
for region in page["regions"]:
print(region["kind"], region["bbox"], region["reason"])
# With options
opts = json.dumps({"mode": "auto", "reconstruct_image_tables": True,
"ocr_languages": ["english"]})
page = json.loads(doc.extract_page_auto(0, opts))
Go — ExtractPageAuto(pageIndex, opts ...AutoOption) (string, error) (gibt JSON zurück; Konfiguration über funktionale Optionen):
package main
import (
"encoding/json"
"fmt"
"log"
pdfoxide "github.com/yfedoseev/pdf_oxide/go"
)
func main() {
doc, err := pdfoxide.Open("mixed-scan.pdf")
if err != nil { log.Fatal(err) }
defer doc.Close()
raw, err := doc.ExtractPageAuto(0)
if err != nil { log.Fatal(err) }
var page map[string]any
json.Unmarshal([]byte(raw), &page)
fmt.Println(page["kind"], page["confidence"], page["ocr_used"])
}
C# — ExtractPageAuto(int pageIndex, string? optionsJson = null) -> string (JSON):
using System.Text.Json;
using PdfOxide.Core;
using var doc = PdfDocument.Open("mixed-scan.pdf");
// Defaults
string json = doc.ExtractPageAuto(0);
using var page = JsonDocument.Parse(json);
Console.WriteLine(page.RootElement.GetProperty("kind"));
// With options
string opts = """{"mode":"auto","ocr_languages":["english"]}""";
string json2 = doc.ExtractPageAuto(0, opts);
Swift — extractPageAuto(_:optionsJson:) -> String (Standard: "{}"):
let json = try doc.extractPageAuto(0, optionsJson: "{}")
JavaScript (WASM) — extractPageAuto(pageIndex, optionsJson?):
import { WasmPdfDocument } from "pdf-oxide-wasm";
const doc = new WasmPdfDocument(bytes);
const page = JSON.parse(doc.extractPageAuto(0));
console.log(page.kind, page.confidence, page.ocr_used);
doc.free();
Rust — der automatische Pfad ist die Bibliotheks-API AutoExtractor. Erstellen Sie AutoExtractOptions (Presets fast(), balanced(), high_fidelity() oder den fluenten Builder) und rufen Sie extract_page auf; es wird ein typisiertes PageExtraction zurückgegeben (kein JSON-Roundtrip):
use pdf_oxide::PdfDocument;
use pdf_oxide::extractors::auto::{AutoExtractor, AutoExtractOptions, ExtractMode};
let doc = PdfDocument::open("mixed-scan.pdf")?;
// Default (balanced) preset
let page = AutoExtractor::new().extract_page(&doc, 0)?;
println!("{:?} conf={} ocr={}", page.kind, page.confidence, page.ocr_used);
// Custom options via the builder
let opts = AutoExtractOptions::builder()
.mode(ExtractMode::Auto)
.reconstruct_image_tables(true)
.ocr_languages(["english"])
.build();
let page = AutoExtractor::with(opts).extract_page(&doc, 0)?;
for region in &page.regions {
println!("{:?} {:?} {:?}", region.kind, region.bbox, region.reason);
}
C++ — extract_page_auto(page, options_json = "") gibt den JSON-Umschlag zurück:
#include <pdf_oxide/pdf_oxide.hpp>
auto doc = pdf_oxide::Document::open("mixed-scan.pdf");
auto json = doc.extract_page_auto(0); // defaults
auto json2 = doc.extract_page_auto(0, R"({"mode":"auto","ocr_languages":["english"]})");
Dart — extractPageAuto(page, [optionsJson]) gibt den JSON-Umschlag zurück:
import 'dart:convert';
import 'package:pdf_oxide/pdf_oxide.dart';
final doc = PdfDocument.open('mixed-scan.pdf');
final page = jsonDecode(doc.extractPageAuto(0));
print('${page["kind"]} ${page["confidence"]} ${page["ocr_used"]}');
doc.close();
R — pdf_extract_page_auto(doc, page, options_json = NULL) gibt JSON zurück:
library(jsonlite)
doc <- pdf_open("mixed-scan.pdf")
page <- fromJSON(pdf_extract_page_auto(doc, 0))
cat(page$kind, page$confidence, page$ocr_used, "\n")
Julia — extract_page_auto(doc, page, options = "{}") gibt JSON zurück:
using PdfOxide, JSON
doc = open_document("mixed-scan.pdf")
page = JSON.parse(extract_page_auto(doc, 0))
println(page["kind"], " ", page["confidence"], " ", page["ocr_used"])
Zig — extractPageAuto(allocator, page, options_json) gibt JSON-Bytes zurück:
const json = try doc.extractPageAuto(a, 0, null); // free json
Objective-C — extractPageAuto:optionsJson:error: gibt den JSON-Umschlag zurück:
NSString *json = [doc extractPageAuto:0 optionsJson:@"{}" error:&err];
Elixir — extract_page_auto(doc, page, options_json \\ "") gibt JSON zurück:
{:ok, json} = PdfOxide.extract_page_auto(doc, 0)
page = Jason.decode!(json)
IO.inspect({page["kind"], page["confidence"], page["ocr_used"]})
Java — der automatische Pfad ist die AutoExtractor-API (extractPage → typisiertes Ergebnis; extractTextForPage für reinen Text):
import fyi.oxide.pdf.PdfDocument;
import fyi.oxide.pdf.AutoExtractor;
try (PdfDocument doc = PdfDocument.open(java.nio.file.Path.of("mixed-scan.pdf"))) {
AutoExtractor ax = AutoExtractor.of(doc); // or .fast/.balanced/.highFidelity
String text = ax.extractTextForPage(0); // graceful native/OCR routing
System.out.println(text);
}
Kotlin
import fyi.oxide.pdf.PdfDocument
import fyi.oxide.pdf.AutoExtractor
PdfDocument.open(java.nio.file.Path.of("mixed-scan.pdf")).use { doc ->
val ax = AutoExtractor.of(doc)
println(ax.extractTextForPage(0))
}
Scala
import fyi.oxide.pdf.{PdfDocument, AutoExtractor}
import scala.util.Using
Using.resource(PdfDocument.open("mixed-scan.pdf")) { doc =>
val ax = AutoExtractor.of(doc)
println(ax.extractTextForPage(0))
}
PHP — der umfangreiche JSON-Umschlag ist über AutoExtractor::extractPageJson erreichbar:
use PdfOxide\PdfDocument;
use PdfOxide\AutoExtractor;
$doc = PdfDocument::open('mixed-scan.pdf');
$ax = AutoExtractor::balanced($doc);
$page = json_decode($ax->extractPageJson(0), true);
echo $page['kind'], ' ', $page['confidence'], ' ', $page['ocr_used'];
Ruby — auto_extractor.extract_page(page) gibt den geparsten Umschlag als Hash zurück:
require 'pdf_oxide'
PdfOxide::PdfDocument.open('mixed-scan.pdf') do |doc|
result = doc.auto_extractor.extract_page(0)
cls = result[:classification] # full PageExtraction JSON as a Hash
puts [cls['kind'], cls['confidence'], cls['ocr_used']].join(' ')
end
Wie erhalte ich strukturierte typisierte Bereiche als JSON?
Für eine seitenübergreifende strukturierte Ansicht — Überschriften, Fließtextblöcke, Kopf-/Fußzeilen, Seitenzahlen und Spaltenreihenfolge — verwenden Sie den Einstiegspunkt zur strukturierten Extraktion. Er gibt eine StructuredPage zurück: page_index, page_width, page_height und ein regions[]-Array, in dem jeder Bereich kind (semantische Rolle), text, bbox, spans und column_index (für mehrspaltige Lesereihenfolge) trägt. Die Bereichs-kinds umfassen Fließtextblöcke, Strukturüberschriften (H1–H6), Randnotizen, laufende Kopf-/Fußzeilen, Seitenzahlen und Artefakte.
Die meisten Bindings geben dies als JSON-String zurück (das C ABI serialisiert einmalig, Bindings deserialisieren in native Typen); Rust gibt die typisierte StructuredPage direkt zurück.
C-ABI-Signatur:
char *pdf_document_extract_structured_to_json(
PdfDocument *handle,
int32_t page_index,
int32_t *error_code);
Python — extract_structured(page) -> str (JSON; mit json.loads deserialisieren):
import json
from pdf_oxide import PdfDocument
doc = PdfDocument("report.pdf")
page = json.loads(doc.extract_structured(0))
print(page["page_width"], page["page_height"])
for region in page["regions"]:
print(region["kind"], region["column_index"], region["text"][:60])
Go — ExtractStructured(page) (string, error):
raw, err := doc.ExtractStructured(0)
if err != nil { log.Fatal(err) }
var page map[string]any
json.Unmarshal([]byte(raw), &page)
for _, r := range page["regions"].([]any) {
region := r.(map[string]any)
fmt.Println(region["kind"], region["text"])
}
C# — ExtractStructured(int page) -> string:
using System.Text.Json;
string json = doc.ExtractStructured(0);
using var page = JsonDocument.Parse(json);
foreach (var region in page.RootElement.GetProperty("regions").EnumerateArray())
{
Console.WriteLine(region.GetProperty("kind"));
}
Swift — extractStructuredJson(_:) -> String:
let json = try doc.extractStructuredJson(0)
JavaScript (WASM) — extractStructured(pageIndex) (gibt einen JSON-String mit camelCase-Schlüsseln zurück):
const page = JSON.parse(doc.extractStructured(0));
for (const region of page.regions) {
console.log(region.kind, region.columnIndex);
}
Rust — extract_structured(page_index) -> Result<StructuredPage> gibt typisierte Bereiche direkt zurück (kein JSON-Roundtrip). Eine Variante extract_structured_with_column_mode ermöglicht es, ColumnMode::Two/Single für schwierige Layouts zu erzwingen:
use pdf_oxide::PdfDocument;
let doc = PdfDocument::open("report.pdf")?;
let page = doc.extract_structured(0)?;
for region in &page.regions {
println!("{:?} col={:?}: {}", region.kind, region.column_index, region.text);
}
C++ — extract_structured_json(page) gibt den JSON-String zurück:
auto json = doc.extract_structured_json(0);
Dart — extractStructuredJson(page) gibt den JSON-String zurück:
import 'dart:convert';
final page = jsonDecode(doc.extractStructuredJson(0));
for (final region in page['regions']) {
print('${region["kind"]} ${region["column_index"]}');
}
R — pdf_extract_structured_json(doc, page) gibt JSON zurück:
library(jsonlite)
page <- fromJSON(pdf_extract_structured_json(doc, 0))
print(page$page_width)
Julia — extract_structured_json(doc, page) gibt JSON zurück:
using JSON
page = JSON.parse(extract_structured_json(doc, 0))
for region in page["regions"]
println(region["kind"], " ", region["column_index"])
end
Zig — extractStructuredJson(allocator, page) gibt JSON-Bytes zurück:
const json = try doc.extractStructuredJson(a, 0); // free json
Objective-C — extractStructuredJson:error: gibt den JSON-String zurück:
NSString *json = [doc extractStructuredJson:0 error:&err];
Elixir — extract_structured_json(doc, page) gibt JSON zurück:
{:ok, json} = PdfOxide.extract_structured_json(doc, 0)
page = Jason.decode!(json)
Java — extractStructured(page) gibt den JSON-String zurück:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
String json = doc.extractStructured(0);
JsonNode page = new ObjectMapper().readTree(json);
for (JsonNode region : page.get("regions")) {
System.out.println(region.get("kind").asText());
}
Kotlin
val json = doc.extractStructured(0) // JSON string; parse with your library of choice
Scala
val json = doc.extractStructured(0) // JSON string
Clojure — (pdf/extract-structured doc page) gibt den JSON-String zurück:
(require '[clojure.data.json :as json])
(with-open [doc (pdf/open "report.pdf")]
(let [page (json/read-str (pdf/extract-structured doc 0))]
(doseq [region (get page "regions")]
(println (get region "kind") (get region "column_index")))))
Ruby — extract_structured(page) gibt den geparsten StructuredPage-Hash zurück:
PdfOxide::PdfDocument.open('report.pdf') do |doc|
page = doc.extract_structured(0)
page['regions'].each { |r| puts "#{r['kind']} #{r['column_index']}" }
end
PHP — extractStructured($page) gibt das deserialisierte assoziative Array zurück:
$doc = PdfOxide\PdfDocument::open('report.pdf');
$page = $doc->extractStructured(0);
foreach ($page['regions'] as $region) {
echo $region['kind'], ' ', $region['column_index'], "\n";
}
Koordinatenreferenz
PDF verwendet einen Ursprung in der unteren linken Ecke, gemessen in Punkten (1 Pt = 1/72 Zoll). Eine Letter-Seite ist (0, 0, 612, 792). Um den obersten 1-Zoll-Streifen anzusprechen, schreiben Sie:
(x, y, w, h) = (0, 792 - 72, 612, 72)
= (0, 720, 612, 72)
Wenn Sie aus einer Bildkoordinaten-Welt (Ursprung oben links) kommen, drehen Sie y entsprechend um.
So ermitteln Sie die tatsächliche MediaBox einer Seite vor der Berechnung:
Python
doc = PdfDocument("doc.pdf")
mb = doc.page_media_box(0) # (llx, lly, urx, ury)
Rust
let mb = editor.get_page_media_box(0)?; // [f32; 4]
Java — page.mediaBox() gibt ein BBox (x0, y0, x1, y1) zurück:
import fyi.oxide.pdf.geometry.BBox;
BBox mb = doc.page(0).mediaBox(); // (x0, y0, x1, y1) in PDF user space
double w = mb.width(), h = mb.height(); // 612 × 792 for US Letter
Kotlin
val mb = doc.page(0).mediaBox() // BBox(x0, y0, x1, y1)
Scala
val mb = doc.page(0).mediaBox // BBox(x0, y0, x1, y1)
C++ — über den Editor: get_page_media_box(page):
auto editor = pdf_oxide::DocumentEditor::open("doc.pdf");
auto mb = editor.get_page_media_box(0); // Bbox{x, y, width, height}
Swift
let editor = try DocumentEditor.open("doc.pdf")
let mb = try editor.getPageMediaBox(0) // Bbox(x, y, width, height)
Dart
final editor = DocumentEditor.open('doc.pdf');
final mb = editor.getPageMediaBox(0); // Bbox(x, y, width, height)
R
editor <- pdf_editor_open("doc.pdf")
mb <- pdf_editor_get_page_media_box(editor, 0) # list(x=, y=, width=, height=)
Julia
editor = open_editor("doc.pdf")
mb = get_page_media_box(editor, 0) # Bbox
Zig
var editor = try pdf_oxide.DocumentEditor.openEditor("doc.pdf");
const mb = try editor.getPageMediaBox(0); // Bbox{ x, y, width, height }
Objective-C
POXDocumentEditor *editor = [POXDocumentEditor openEditor:@"doc.pdf" error:&err];
POXBbox mb = [editor pageMediaBox:0 error:&err]; // {x, y, width, height}
Elixir
{:ok, editor} = PdfOxide.open_editor("doc.pdf")
{:ok, mb} = PdfOxide.get_page_media_box(editor, 0) # %Bbox{}
Go / C# — in-rect-Hilfsfunktionen
Go und C# bieten die fluente within()-Kette noch nicht, aber die zugrunde liegenden Low-Level-Methoden sind dieselben:
| Methode | Go | C# |
|---|---|---|
| Text im Rechteck | doc.ExtractTextInRect(page, x, y, w, h) |
doc.ExtractTextInRect(page, x, y, w, h) |
| Wörter im Rechteck | doc.ExtractWordsInRect(page, x, y, w, h) |
(noch nicht eingebunden) |
| Bilder im Rechteck | doc.ExtractImagesInRect(page, x, y, w, h) |
(noch nicht eingebunden) |
Für Muster, die mehrere Extraktionstypen auf dasselbe Rechteck in Go oder C# anwenden müssen, halten Sie das Rechteck in Variablen und rufen Sie die Hilfsfunktionen nacheinander auf. Die fluente Oberfläche folgt, sobald die Editor-API stabil ist.
Häufig gestellte Fragen
Was ist der Unterschied zwischen extract_words() und extract_lines_in_rect() in einem Bereich?
extract_words() gibt einen Datensatz pro Wort zurück; extract_lines_in_rect() gibt einen Datensatz pro Zeile (Text, Bounding Box und Wortzahl) für die Zeilen zurück, deren Bounding Box das Rechteck schneidet. Verwenden Sie Zeilen, wenn Sie ganze Zeilen in Lesereihenfolge benötigen — Adressblöcke, Kontoauszugszeilen, mehrzeilige Summen — ohne Wörter selbst gruppieren zu müssen.
Führt extract_page_auto immer OCR aus?
Nein. Das Routing erfolgt bereichsweise. Im Standard-Modus "auto" wird OCR nur dann eskaliert, wenn die native Textschicht fehlt oder zweifelhaft ist, und OCR wird tatsächlich nur ausgeführt, wenn die Bibliothek mit der Feature ocr gebaut wurde. Ohne diese Feature fällt es auf die native Textschicht zurück und erzeugt keinen undurchsichtigen OCR-Fehler.
Welche Bindings bieten die Varianten lines-in-rect und tables-in-rect?
Rust, das C ABI und Swift bieten extract_lines_in_rect / extract_tables_in_rect direkt. Python erreicht dieselben Ergebnisse über den fluenten Bereich (within(...).extract_text_lines() und within(...).extract_tables()). Go und C# binden die in-rect-Einstiegspunkte für Zeilen/Tabellen noch nicht ein — extrahieren Sie für die gesamte Seite und filtern Sie nach den zurückgegebenen Bounding Boxes.
Wie schnell ist die Bereichsextraktion? Die Bereichsbegrenzung fügt keinen messbaren Overhead gegenüber der Ganzseiten-Extraktion hinzu — PDF Oxide extrahiert mit einem Mittlewert von 0,8 ms (100 % Bestehensrate im Benchmark-Korpus), und ein in-rect-Aufruf filtert dasselbe Ergebnis lediglich nach Bounding Box.
Verwandte Seiten
- Textextraktion — Ganzseiten-Extraktion
- Tabellen aus PDF extrahieren — strukturierte Tabellen
- Textsuche — Suchergebnisse und
search_results_to_json-Serialisierung - Extraktionsprofile — dokumentenspezifische Extraktionsanpassung
- Seiten-API-Referenz — Iterieren und Begrenzen von einem
Page-Objekt aus (page.region(rect))