Skip to content

Commit 6487072

Browse files
examples: Add PDF text extraction example script
- Added `extract_pdf_text_example.py` to demonstrate text extraction, including word-level coordinates and style metadata from `examples/resources/report.pdf`. - Rendered extracted data as a Rich table for structured visualization. - Updated `README.md` to document the available examples. Assisted-by: Codex
1 parent a6eda00 commit 6487072

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

examples/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,10 @@ that via `.env` if desired), upload the checked-in sample assets under
1818
`examples/resources/`, and exercise the async client end-to-end. Use
1919
`uvx nox -s examples` when you want to execute every example across the
2020
supported interpreter matrix.
21+
22+
## Available Examples
23+
24+
- `examples/delete/delete_example.py` – demonstrate file deletion (sync + async
25+
variants).
26+
- `examples/extract_text/extract_pdf_text_example.py` – run `extract_pdf_text`
27+
with word coordinates/style enabled and render the output as a Rich table.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# /// script
2+
# requires-python = ">=3.10"
3+
# dependencies = ["pdfrest", "python-dotenv", "rich"]
4+
# ///
5+
"""Render extracted words with coordinates and style metadata.
6+
7+
This sample demonstrates how to:
8+
9+
1. Upload the bundled ``examples/resources/report.pdf`` resource.
10+
2. Request JSON output from :func:`PdfRestClient.extract_pdf_text` while turning on
11+
word-level coordinates and styling data.
12+
3. Display the returned metadata as a Rich table.
13+
14+
Run with ``uv run --project ../.. python extract_pdf_text_example.py`` after
15+
setting ``PDFREST_API_KEY`` (``python-dotenv`` will also load `.env` if present).
16+
"""
17+
18+
from __future__ import annotations
19+
20+
from pathlib import Path
21+
22+
from dotenv import load_dotenv
23+
from rich.console import Console
24+
from rich.table import Table
25+
26+
from pdfrest import PdfRestClient
27+
from pdfrest.models import (
28+
ExtractedTextDocument,
29+
ExtractedTextPoint,
30+
ExtractedTextWord,
31+
ExtractedTextWordCoordinates,
32+
)
33+
34+
RESOURCE = Path(__file__).resolve().parents[1] / "resources" / "report.pdf"
35+
36+
37+
def _format_point(point: ExtractedTextPoint | None) -> str:
38+
if point is None:
39+
return "—"
40+
return f"({point.x:.2f}, {point.y:.2f})"
41+
42+
43+
def _format_color(word: ExtractedTextWord) -> str:
44+
style = word.style
45+
if style is None or style.color is None:
46+
return "—"
47+
color = style.color
48+
values = ", ".join(str(value) for value in color.values)
49+
return f"{color.space}: {values}"
50+
51+
52+
def _format_font(word: ExtractedTextWord) -> str:
53+
style = word.style
54+
if style is None or style.font is None:
55+
return "—"
56+
font = style.font
57+
name = font.name or "Unknown"
58+
size = f"{font.size:.1f} pt" if font.size is not None else "Unknown size"
59+
return f"{name} ({size})"
60+
61+
62+
def _build_word_table(document: ExtractedTextDocument) -> Table:
63+
table = Table(title="Extracted Words with Coordinates and Style")
64+
table.add_column("Word", style="bold")
65+
table.add_column("Page", justify="right")
66+
table.add_column("Top Left")
67+
table.add_column("Top Right")
68+
table.add_column("Bottom Left")
69+
table.add_column("Bottom Right")
70+
table.add_column("Color")
71+
table.add_column("Font")
72+
73+
for word in document.words or []:
74+
coords: ExtractedTextWordCoordinates | None = word.coordinates
75+
table.add_row(
76+
word.text,
77+
str(word.page),
78+
_format_point(coords.top_left if coords else None),
79+
_format_point(coords.top_right if coords else None),
80+
_format_point(coords.bottom_left if coords else None),
81+
_format_point(coords.bottom_right if coords else None),
82+
_format_color(word),
83+
_format_font(word),
84+
)
85+
return table
86+
87+
88+
def list_words_with_coordinates() -> None:
89+
load_dotenv()
90+
console = Console()
91+
92+
with PdfRestClient() as client:
93+
uploaded = client.files.create_from_paths([RESOURCE])[0]
94+
document = client.extract_pdf_text(
95+
uploaded,
96+
full_text="by_page",
97+
preserve_line_breaks=True,
98+
word_style=True,
99+
word_coordinates=True,
100+
)
101+
102+
words = document.words or []
103+
console.print(f"Extracted {len(words)} words from [bold]{uploaded.name}[/bold].")
104+
if not words:
105+
console.print("[yellow]This document did not include word metadata.[/yellow]")
106+
return
107+
108+
table = _build_word_table(document)
109+
console.print(table)
110+
111+
112+
if __name__ == "__main__": # pragma: no cover - manual example
113+
list_words_with_coordinates()

0 commit comments

Comments
 (0)