rasgapdf 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rasgapdf-0.1.2/PKG-INFO +157 -0
- rasgapdf-0.1.2/README.md +141 -0
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/pyproject.toml +4 -3
- rasgapdf-0.1.2/rasgapdf.egg-info/PKG-INFO +157 -0
- rasgapdf-0.1.0/PKG-INFO +0 -203
- rasgapdf-0.1.0/README.md +0 -188
- rasgapdf-0.1.0/rasgapdf.egg-info/PKG-INFO +0 -203
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/rasgapdf/__init__.py +0 -0
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/rasgapdf/librasgapdf.so +0 -0
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/rasgapdf.egg-info/SOURCES.txt +0 -0
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/rasgapdf.egg-info/dependency_links.txt +0 -0
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/rasgapdf.egg-info/top_level.txt +0 -0
- {rasgapdf-0.1.0 → rasgapdf-0.1.2}/setup.cfg +0 -0
rasgapdf-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rasgapdf
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Ultra-fast 2D spatial PDF parser powered by Rust
|
|
5
|
+
Author: Messias Martins
|
|
6
|
+
Project-URL: Homepage, https://huggingface.co/martinsmessias/rasgapdf
|
|
7
|
+
Project-URL: Repository, https://huggingface.co/martinsmessias/rasgapdf
|
|
8
|
+
Project-URL: Discussions, https://huggingface.co/martinsmessias/rasgapdf/discussions
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Rust
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Topic :: Text Processing :: General
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# ⚡ RasgaPDF
|
|
18
|
+
|
|
19
|
+
<div align="center">
|
|
20
|
+
|
|
21
|
+
**The Blazing-Fast 2D Spatial PDF Parser for Python.**
|
|
22
|
+
*Extract exact physical coordinates `[x0, y0, x1, y1]`, word spans, text blocks, and tabular structures at native hardware speeds.*
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/rasgapdf/)
|
|
25
|
+
[](https://pypi.org/project/rasgapdf/)
|
|
26
|
+
[](https://opensource.org/licenses/MIT)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🚀 Why RasgaPDF?
|
|
33
|
+
|
|
34
|
+
Most Python PDF extraction libraries make fragile guesses: they flatten multi-column layouts into corrupted text streams, mangle tables, and strip away 2D positional geometry.
|
|
35
|
+
|
|
36
|
+
**RasgaPDF does one thing with uncompromising precision:**
|
|
37
|
+
It returns the **exact 2D physical spatial geometry** of the PDF directly to Python:
|
|
38
|
+
|
|
39
|
+
- **Exact Bounding Boxes:** Every character, word span, line, block, and table has exact coordinates `[x0, y0, x1, y1]`.
|
|
40
|
+
- **Zero Lossy Heuristics:** No broken markdown assumptions. Downstream LLMs, RAG pipelines, or vision-language models receive the true physical layout.
|
|
41
|
+
- **Pure Native Speed:** Powered by a SIMD-parallelized Rust core. Extracts typical pages in **~3 to 8 ms**.
|
|
42
|
+
- **Self-Contained Wheel:** Pre-compiled native binaries bundled directly in the wheel. Zero external runtime dependencies.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## ⚡ Quick Benchmarks (Python)
|
|
47
|
+
|
|
48
|
+
Measured on Intel Core i7-1365U (Single-thread latency, 1-page complex PDF):
|
|
49
|
+
|
|
50
|
+
| Library | Parse Time | Output Type | Spatial Accuracy |
|
|
51
|
+
| :--- | :--- | :--- | :--- |
|
|
52
|
+
| **⚡ RasgaPDF (`parse_raw`)** | **~7.7 ms** | **Flat Coordinates `[x0, y0, x1, y1]`** | **Exact Physical Canvas** |
|
|
53
|
+
| **🚀 RasgaPDF (`parse_pdf`)** | **~8.5 ms** | **Hierarchical Blocks & Tables** | **Exact Physical Canvas** |
|
|
54
|
+
| PyMuPDF (`fitz`) | ~28.0 ms | Text / Pixmaps | Bounding Boxes |
|
|
55
|
+
| `pdfplumber` | ~410.0 ms | Python Dicts | High Overhead |
|
|
56
|
+
| `pypdf` | ~95.0 ms | Plain String | No Geometry |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 📦 Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install --upgrade rasgapdf
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 💡 Usage
|
|
69
|
+
|
|
70
|
+
RasgaPDF offers two distinct modes for Python engineers:
|
|
71
|
+
|
|
72
|
+
### ⚡ Mode 1: Raw Physical Coordinates (`parse_raw`)
|
|
73
|
+
The fastest and most direct extraction possible. Returns a flat list of physical 2D coordinates for every text span on the page, with zero block/table overhead (~3-8 ms):
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import rasgapdf
|
|
77
|
+
|
|
78
|
+
# Parse raw physical coordinates
|
|
79
|
+
doc = rasgapdf.parse_raw("document.pdf")
|
|
80
|
+
|
|
81
|
+
print(f"Extracted {doc['total_spans']} spans in {doc['parse_time_ms']:.2f} ms")
|
|
82
|
+
|
|
83
|
+
for span in doc["spans"]:
|
|
84
|
+
print(
|
|
85
|
+
f"[Page {span['page']}] "
|
|
86
|
+
f"bbox=({span['x0']:.2f}, {span['y0']:.2f}, {span['x1']:.2f}, {span['y1']:.2f}) "
|
|
87
|
+
f"font={span['font_name']} ({span['font_size']}pt) "
|
|
88
|
+
f"text=\"{span['text']}\""
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Output Structure:
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"file_name": "document.pdf",
|
|
96
|
+
"total_pages": 1,
|
|
97
|
+
"total_spans": 20,
|
|
98
|
+
"parse_time_ms": 7.78,
|
|
99
|
+
"spans": [
|
|
100
|
+
{
|
|
101
|
+
"page": 1,
|
|
102
|
+
"x0": 50.0,
|
|
103
|
+
"y0": 67.0,
|
|
104
|
+
"x1": 244.0,
|
|
105
|
+
"y1": 83.0,
|
|
106
|
+
"font_size": 12.0,
|
|
107
|
+
"font_name": "Helvetica",
|
|
108
|
+
"text": "The Future of Artificial Intelligence"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 🎯 Mode 2: Hierarchical Structured Document (`parse_pdf`)
|
|
117
|
+
Parses the visual hierarchy: paragraphs (`text_blocks`), text lines (`lines`), spans, and auto-detects matrix tables via column alignment:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import rasgapdf
|
|
121
|
+
|
|
122
|
+
doc = rasgapdf.parse_pdf("invoice.pdf", detect_tables=True)
|
|
123
|
+
|
|
124
|
+
for page in doc["pages"]:
|
|
125
|
+
print(f"--- Page {page['page_number']} ({page['width']}x{page['height']} pt) ---")
|
|
126
|
+
|
|
127
|
+
# 1. Inspect Text Blocks
|
|
128
|
+
for block in page["text_blocks"]:
|
|
129
|
+
print(f"Block #{block['block_id']} at {block['bbox']}:")
|
|
130
|
+
for line in block["lines"]:
|
|
131
|
+
print(f" Line: {line['text']}")
|
|
132
|
+
|
|
133
|
+
# 2. Inspect Detected Tables
|
|
134
|
+
for table in page["tables"]:
|
|
135
|
+
print(f"Table ({table['col_count']} cols x {table['row_count']} rows):")
|
|
136
|
+
print("Headers:", table["headers"])
|
|
137
|
+
for row in table["rows"]:
|
|
138
|
+
print("Row:", row)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## ⚙️ Parameters for `parse_pdf`
|
|
144
|
+
|
|
145
|
+
| Parameter | Type | Default | Description |
|
|
146
|
+
| :--- | :--- | :--- | :--- |
|
|
147
|
+
| `file_path` | `str` | *required* | Path to the PDF file on disk |
|
|
148
|
+
| `detect_tables` | `bool` | `True` | Automatically detect and reconstruct tables |
|
|
149
|
+
| `min_table_cols` | `int` | `3` | Minimum number of columns required to classify as a table |
|
|
150
|
+
| `col_tolerance` | `float` | `16.0` | Horizontal alignment threshold in typographical points |
|
|
151
|
+
| `row_tolerance` | `float` | `6.0` | Vertical line clustering threshold in points |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 📄 License
|
|
156
|
+
|
|
157
|
+
MIT License. Copyright (c) 2026 Messias Martins.
|
rasgapdf-0.1.2/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# ⚡ RasgaPDF
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**The Blazing-Fast 2D Spatial PDF Parser for Python.**
|
|
6
|
+
*Extract exact physical coordinates `[x0, y0, x1, y1]`, word spans, text blocks, and tabular structures at native hardware speeds.*
|
|
7
|
+
|
|
8
|
+
[](https://pypi.org/project/rasgapdf/)
|
|
9
|
+
[](https://pypi.org/project/rasgapdf/)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 🚀 Why RasgaPDF?
|
|
17
|
+
|
|
18
|
+
Most Python PDF extraction libraries make fragile guesses: they flatten multi-column layouts into corrupted text streams, mangle tables, and strip away 2D positional geometry.
|
|
19
|
+
|
|
20
|
+
**RasgaPDF does one thing with uncompromising precision:**
|
|
21
|
+
It returns the **exact 2D physical spatial geometry** of the PDF directly to Python:
|
|
22
|
+
|
|
23
|
+
- **Exact Bounding Boxes:** Every character, word span, line, block, and table has exact coordinates `[x0, y0, x1, y1]`.
|
|
24
|
+
- **Zero Lossy Heuristics:** No broken markdown assumptions. Downstream LLMs, RAG pipelines, or vision-language models receive the true physical layout.
|
|
25
|
+
- **Pure Native Speed:** Powered by a SIMD-parallelized Rust core. Extracts typical pages in **~3 to 8 ms**.
|
|
26
|
+
- **Self-Contained Wheel:** Pre-compiled native binaries bundled directly in the wheel. Zero external runtime dependencies.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## ⚡ Quick Benchmarks (Python)
|
|
31
|
+
|
|
32
|
+
Measured on Intel Core i7-1365U (Single-thread latency, 1-page complex PDF):
|
|
33
|
+
|
|
34
|
+
| Library | Parse Time | Output Type | Spatial Accuracy |
|
|
35
|
+
| :--- | :--- | :--- | :--- |
|
|
36
|
+
| **⚡ RasgaPDF (`parse_raw`)** | **~7.7 ms** | **Flat Coordinates `[x0, y0, x1, y1]`** | **Exact Physical Canvas** |
|
|
37
|
+
| **🚀 RasgaPDF (`parse_pdf`)** | **~8.5 ms** | **Hierarchical Blocks & Tables** | **Exact Physical Canvas** |
|
|
38
|
+
| PyMuPDF (`fitz`) | ~28.0 ms | Text / Pixmaps | Bounding Boxes |
|
|
39
|
+
| `pdfplumber` | ~410.0 ms | Python Dicts | High Overhead |
|
|
40
|
+
| `pypdf` | ~95.0 ms | Plain String | No Geometry |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 📦 Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install --upgrade rasgapdf
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 💡 Usage
|
|
53
|
+
|
|
54
|
+
RasgaPDF offers two distinct modes for Python engineers:
|
|
55
|
+
|
|
56
|
+
### ⚡ Mode 1: Raw Physical Coordinates (`parse_raw`)
|
|
57
|
+
The fastest and most direct extraction possible. Returns a flat list of physical 2D coordinates for every text span on the page, with zero block/table overhead (~3-8 ms):
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import rasgapdf
|
|
61
|
+
|
|
62
|
+
# Parse raw physical coordinates
|
|
63
|
+
doc = rasgapdf.parse_raw("document.pdf")
|
|
64
|
+
|
|
65
|
+
print(f"Extracted {doc['total_spans']} spans in {doc['parse_time_ms']:.2f} ms")
|
|
66
|
+
|
|
67
|
+
for span in doc["spans"]:
|
|
68
|
+
print(
|
|
69
|
+
f"[Page {span['page']}] "
|
|
70
|
+
f"bbox=({span['x0']:.2f}, {span['y0']:.2f}, {span['x1']:.2f}, {span['y1']:.2f}) "
|
|
71
|
+
f"font={span['font_name']} ({span['font_size']}pt) "
|
|
72
|
+
f"text=\"{span['text']}\""
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### Output Structure:
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"file_name": "document.pdf",
|
|
80
|
+
"total_pages": 1,
|
|
81
|
+
"total_spans": 20,
|
|
82
|
+
"parse_time_ms": 7.78,
|
|
83
|
+
"spans": [
|
|
84
|
+
{
|
|
85
|
+
"page": 1,
|
|
86
|
+
"x0": 50.0,
|
|
87
|
+
"y0": 67.0,
|
|
88
|
+
"x1": 244.0,
|
|
89
|
+
"y1": 83.0,
|
|
90
|
+
"font_size": 12.0,
|
|
91
|
+
"font_name": "Helvetica",
|
|
92
|
+
"text": "The Future of Artificial Intelligence"
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### 🎯 Mode 2: Hierarchical Structured Document (`parse_pdf`)
|
|
101
|
+
Parses the visual hierarchy: paragraphs (`text_blocks`), text lines (`lines`), spans, and auto-detects matrix tables via column alignment:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import rasgapdf
|
|
105
|
+
|
|
106
|
+
doc = rasgapdf.parse_pdf("invoice.pdf", detect_tables=True)
|
|
107
|
+
|
|
108
|
+
for page in doc["pages"]:
|
|
109
|
+
print(f"--- Page {page['page_number']} ({page['width']}x{page['height']} pt) ---")
|
|
110
|
+
|
|
111
|
+
# 1. Inspect Text Blocks
|
|
112
|
+
for block in page["text_blocks"]:
|
|
113
|
+
print(f"Block #{block['block_id']} at {block['bbox']}:")
|
|
114
|
+
for line in block["lines"]:
|
|
115
|
+
print(f" Line: {line['text']}")
|
|
116
|
+
|
|
117
|
+
# 2. Inspect Detected Tables
|
|
118
|
+
for table in page["tables"]:
|
|
119
|
+
print(f"Table ({table['col_count']} cols x {table['row_count']} rows):")
|
|
120
|
+
print("Headers:", table["headers"])
|
|
121
|
+
for row in table["rows"]:
|
|
122
|
+
print("Row:", row)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## ⚙️ Parameters for `parse_pdf`
|
|
128
|
+
|
|
129
|
+
| Parameter | Type | Default | Description |
|
|
130
|
+
| :--- | :--- | :--- | :--- |
|
|
131
|
+
| `file_path` | `str` | *required* | Path to the PDF file on disk |
|
|
132
|
+
| `detect_tables` | `bool` | `True` | Automatically detect and reconstruct tables |
|
|
133
|
+
| `min_table_cols` | `int` | `3` | Minimum number of columns required to classify as a table |
|
|
134
|
+
| `col_tolerance` | `float` | `16.0` | Horizontal alignment threshold in typographical points |
|
|
135
|
+
| `row_tolerance` | `float` | `6.0` | Vertical line clustering threshold in points |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 📄 License
|
|
140
|
+
|
|
141
|
+
MIT License. Copyright (c) 2026 Messias Martins.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rasgapdf"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Messias Martins" },
|
|
10
10
|
]
|
|
@@ -21,8 +21,9 @@ classifiers = [
|
|
|
21
21
|
dependencies = []
|
|
22
22
|
|
|
23
23
|
[project.urls]
|
|
24
|
-
"Homepage" = "https://
|
|
25
|
-
"
|
|
24
|
+
"Homepage" = "https://huggingface.co/martinsmessias/rasgapdf"
|
|
25
|
+
"Repository" = "https://huggingface.co/martinsmessias/rasgapdf"
|
|
26
|
+
"Discussions" = "https://huggingface.co/martinsmessias/rasgapdf/discussions"
|
|
26
27
|
|
|
27
28
|
[tool.setuptools.packages.find]
|
|
28
29
|
where = ["."]
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rasgapdf
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Ultra-fast 2D spatial PDF parser powered by Rust
|
|
5
|
+
Author: Messias Martins
|
|
6
|
+
Project-URL: Homepage, https://huggingface.co/martinsmessias/rasgapdf
|
|
7
|
+
Project-URL: Repository, https://huggingface.co/martinsmessias/rasgapdf
|
|
8
|
+
Project-URL: Discussions, https://huggingface.co/martinsmessias/rasgapdf/discussions
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Rust
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Topic :: Text Processing :: General
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# ⚡ RasgaPDF
|
|
18
|
+
|
|
19
|
+
<div align="center">
|
|
20
|
+
|
|
21
|
+
**The Blazing-Fast 2D Spatial PDF Parser for Python.**
|
|
22
|
+
*Extract exact physical coordinates `[x0, y0, x1, y1]`, word spans, text blocks, and tabular structures at native hardware speeds.*
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/rasgapdf/)
|
|
25
|
+
[](https://pypi.org/project/rasgapdf/)
|
|
26
|
+
[](https://opensource.org/licenses/MIT)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🚀 Why RasgaPDF?
|
|
33
|
+
|
|
34
|
+
Most Python PDF extraction libraries make fragile guesses: they flatten multi-column layouts into corrupted text streams, mangle tables, and strip away 2D positional geometry.
|
|
35
|
+
|
|
36
|
+
**RasgaPDF does one thing with uncompromising precision:**
|
|
37
|
+
It returns the **exact 2D physical spatial geometry** of the PDF directly to Python:
|
|
38
|
+
|
|
39
|
+
- **Exact Bounding Boxes:** Every character, word span, line, block, and table has exact coordinates `[x0, y0, x1, y1]`.
|
|
40
|
+
- **Zero Lossy Heuristics:** No broken markdown assumptions. Downstream LLMs, RAG pipelines, or vision-language models receive the true physical layout.
|
|
41
|
+
- **Pure Native Speed:** Powered by a SIMD-parallelized Rust core. Extracts typical pages in **~3 to 8 ms**.
|
|
42
|
+
- **Self-Contained Wheel:** Pre-compiled native binaries bundled directly in the wheel. Zero external runtime dependencies.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## ⚡ Quick Benchmarks (Python)
|
|
47
|
+
|
|
48
|
+
Measured on Intel Core i7-1365U (Single-thread latency, 1-page complex PDF):
|
|
49
|
+
|
|
50
|
+
| Library | Parse Time | Output Type | Spatial Accuracy |
|
|
51
|
+
| :--- | :--- | :--- | :--- |
|
|
52
|
+
| **⚡ RasgaPDF (`parse_raw`)** | **~7.7 ms** | **Flat Coordinates `[x0, y0, x1, y1]`** | **Exact Physical Canvas** |
|
|
53
|
+
| **🚀 RasgaPDF (`parse_pdf`)** | **~8.5 ms** | **Hierarchical Blocks & Tables** | **Exact Physical Canvas** |
|
|
54
|
+
| PyMuPDF (`fitz`) | ~28.0 ms | Text / Pixmaps | Bounding Boxes |
|
|
55
|
+
| `pdfplumber` | ~410.0 ms | Python Dicts | High Overhead |
|
|
56
|
+
| `pypdf` | ~95.0 ms | Plain String | No Geometry |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 📦 Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install --upgrade rasgapdf
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 💡 Usage
|
|
69
|
+
|
|
70
|
+
RasgaPDF offers two distinct modes for Python engineers:
|
|
71
|
+
|
|
72
|
+
### ⚡ Mode 1: Raw Physical Coordinates (`parse_raw`)
|
|
73
|
+
The fastest and most direct extraction possible. Returns a flat list of physical 2D coordinates for every text span on the page, with zero block/table overhead (~3-8 ms):
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import rasgapdf
|
|
77
|
+
|
|
78
|
+
# Parse raw physical coordinates
|
|
79
|
+
doc = rasgapdf.parse_raw("document.pdf")
|
|
80
|
+
|
|
81
|
+
print(f"Extracted {doc['total_spans']} spans in {doc['parse_time_ms']:.2f} ms")
|
|
82
|
+
|
|
83
|
+
for span in doc["spans"]:
|
|
84
|
+
print(
|
|
85
|
+
f"[Page {span['page']}] "
|
|
86
|
+
f"bbox=({span['x0']:.2f}, {span['y0']:.2f}, {span['x1']:.2f}, {span['y1']:.2f}) "
|
|
87
|
+
f"font={span['font_name']} ({span['font_size']}pt) "
|
|
88
|
+
f"text=\"{span['text']}\""
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Output Structure:
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"file_name": "document.pdf",
|
|
96
|
+
"total_pages": 1,
|
|
97
|
+
"total_spans": 20,
|
|
98
|
+
"parse_time_ms": 7.78,
|
|
99
|
+
"spans": [
|
|
100
|
+
{
|
|
101
|
+
"page": 1,
|
|
102
|
+
"x0": 50.0,
|
|
103
|
+
"y0": 67.0,
|
|
104
|
+
"x1": 244.0,
|
|
105
|
+
"y1": 83.0,
|
|
106
|
+
"font_size": 12.0,
|
|
107
|
+
"font_name": "Helvetica",
|
|
108
|
+
"text": "The Future of Artificial Intelligence"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 🎯 Mode 2: Hierarchical Structured Document (`parse_pdf`)
|
|
117
|
+
Parses the visual hierarchy: paragraphs (`text_blocks`), text lines (`lines`), spans, and auto-detects matrix tables via column alignment:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import rasgapdf
|
|
121
|
+
|
|
122
|
+
doc = rasgapdf.parse_pdf("invoice.pdf", detect_tables=True)
|
|
123
|
+
|
|
124
|
+
for page in doc["pages"]:
|
|
125
|
+
print(f"--- Page {page['page_number']} ({page['width']}x{page['height']} pt) ---")
|
|
126
|
+
|
|
127
|
+
# 1. Inspect Text Blocks
|
|
128
|
+
for block in page["text_blocks"]:
|
|
129
|
+
print(f"Block #{block['block_id']} at {block['bbox']}:")
|
|
130
|
+
for line in block["lines"]:
|
|
131
|
+
print(f" Line: {line['text']}")
|
|
132
|
+
|
|
133
|
+
# 2. Inspect Detected Tables
|
|
134
|
+
for table in page["tables"]:
|
|
135
|
+
print(f"Table ({table['col_count']} cols x {table['row_count']} rows):")
|
|
136
|
+
print("Headers:", table["headers"])
|
|
137
|
+
for row in table["rows"]:
|
|
138
|
+
print("Row:", row)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## ⚙️ Parameters for `parse_pdf`
|
|
144
|
+
|
|
145
|
+
| Parameter | Type | Default | Description |
|
|
146
|
+
| :--- | :--- | :--- | :--- |
|
|
147
|
+
| `file_path` | `str` | *required* | Path to the PDF file on disk |
|
|
148
|
+
| `detect_tables` | `bool` | `True` | Automatically detect and reconstruct tables |
|
|
149
|
+
| `min_table_cols` | `int` | `3` | Minimum number of columns required to classify as a table |
|
|
150
|
+
| `col_tolerance` | `float` | `16.0` | Horizontal alignment threshold in typographical points |
|
|
151
|
+
| `row_tolerance` | `float` | `6.0` | Vertical line clustering threshold in points |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 📄 License
|
|
156
|
+
|
|
157
|
+
MIT License. Copyright (c) 2026 Messias Martins.
|
rasgapdf-0.1.0/PKG-INFO
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: rasgapdf
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Ultra-fast 2D spatial PDF parser powered by Rust
|
|
5
|
-
Author: Messias Martins
|
|
6
|
-
Project-URL: Homepage, https://github.com/messiasmartins/rasgapdf
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/messiasmartins/rasgapdf/issues
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Rust
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
-
Classifier: Topic :: Text Processing :: General
|
|
13
|
-
Requires-Python: >=3.8
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
|
-
# ⚡ RasgaPDF
|
|
17
|
-
|
|
18
|
-
<div align="center">
|
|
19
|
-
|
|
20
|
-
**The Blazing-Fast 2D Spatial PDF Parser powered by Pure Rust.**
|
|
21
|
-
*Extract exact physical coordinates (Raw X/Y) or structured blocks & tables at native hardware speeds.*
|
|
22
|
-
|
|
23
|
-
[](LICENSE)
|
|
24
|
-
[](Cargo.toml)
|
|
25
|
-
[](bindings/python)
|
|
26
|
-
[](bindings/nodejs)
|
|
27
|
-
[](bindings/go)
|
|
28
|
-
[](bindings/csharp)
|
|
29
|
-
[](https://huggingface.co/martinsmessias/rasgapdf)
|
|
30
|
-
|
|
31
|
-
[**Live Gradio Demo**](#-interactive-gradio-demo) • [**Quickstart**](#-quickstart) • [**Two Modes**](#-two-parsing-modes) • [**Architecture**](docs/ARCHITECTURE.md) • [**Spatial Schema**](docs/SCHEMA.md) • [**Contributing**](CONTRIBUTING.md)
|
|
32
|
-
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 🎯 The Philosophy: Pure Spatial Parsing
|
|
38
|
-
|
|
39
|
-
Most PDF libraries make fragile guesses: they convert multi-column documents into flat, corrupted text streams, mangle tables, and strip away spatial geometry.
|
|
40
|
-
|
|
41
|
-
**RasgaPDF does one thing with uncompromising precision:**
|
|
42
|
-
It returns the **exact 2D physical spatial geometry** of the PDF.
|
|
43
|
-
|
|
44
|
-
- **Bounding Boxes Everywhere:** Every character, word span, line, block, and table has exact coordinates `[x0, y0, x1, y1]`.
|
|
45
|
-
- **Zero Lossy Guesswork:** No broken heuristics pretending to be Markdown. Your downstream LLMs, RAG pipelines, or OCR validators receive the true physical layout.
|
|
46
|
-
- **Microsecond Rayon Parallelism:** Multi-threaded page processing in pure Rust utilizing AVX2/AVX-512 SIMD.
|
|
47
|
-
- **Polyglot First:** Native C-ABI FFI bindings for **Python**, **Node.js**, **Go**, and **C# (.NET)**.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## ⚡ Two Parsing Modes
|
|
52
|
-
|
|
53
|
-
RasgaPDF offers two distinct modes for different engineering needs:
|
|
54
|
-
|
|
55
|
-
### ⚡ Modo 1: Coordenadas Brutas (Raw X/Y Puro)
|
|
56
|
-
O retorno mais direto, bruto e rápido possível. Retorna exclusivamente a lista plana de coordenadas físicas de cada elemento desenhado na página, sem criar hierarquias de blocos ou overhead de tabelas:
|
|
57
|
-
- **Latência:** ~3 a 8 ms por página
|
|
58
|
-
- **Saídas suportadas:** JSON plano, Text formatado, TSV ou CSV
|
|
59
|
-
- **Uso ideal:** RAG espacial, visualizadores 2D, indexação vetorial, pipelines Unix com `awk`/`grep`.
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
[Pág. 1] (X0: 50.00, Y0: 67.00, X1: 244.00, Y1: 83.00) [12.0pt] A Revolução da Inteligência Artificial
|
|
63
|
-
[Pág. 1] (X0: 50.00, Y0: 103.00, X1: 478.00, Y1: 119.00) [12.0pt] A Inteligência Artificial (IA) tem transformado...
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 🎯 Modo 2: Estruturado Hierárquico
|
|
67
|
-
Processa a geometria e agrupa elementos em parágrafos visuais (`blocks`), linhas (`lines`), spans de fonte e detecta matrizes de tabelas automaticamente via projeção horizontal de colunas:
|
|
68
|
-
- **Latência:** ~8 a 15 ms por página
|
|
69
|
-
- **Saída:** Árvore hierárquica `SpatialDocument` -> `pages` -> `text_blocks` -> `lines` -> `tables`.
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## ⚡ Performance Benchmark
|
|
74
|
-
|
|
75
|
-
Measured on Intel Core i7-1365U (10 Cores / 12 Threads, AVX2):
|
|
76
|
-
|
|
77
|
-
| Library / Tool | Language | Single Page | 50 Pages | Memory Footprint | Output Type |
|
|
78
|
-
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
79
|
-
| **⚡ RasgaPDF (Raw X/Y)** | **Rust (Native)** | **7.7 ms** | **95 ms** | **~14 MB** | **Flat Raw Coordinates** |
|
|
80
|
-
| **🚀 RasgaPDF (Structured)**| **Rust (Native)** | **8.5 ms** | **142 ms** | **~18 MB** | **Spatial Blocks & Tables** |
|
|
81
|
-
| PyMuPDF (`fitz`) | C / Python | 28.0 ms | 620 ms | ~45 MB | Text / Pixmap |
|
|
82
|
-
| `pdfplumber` | Python | 410.0 ms | 9,800 ms | ~140 MB | Python dicts |
|
|
83
|
-
| `pypdf` | Python | 95.0 ms | 2,100 ms | ~85 MB | Flat text string |
|
|
84
|
-
| Apache Tika | Java | 650.0 ms | 12,400 ms | ~320 MB | XHTML |
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## 💻 Standalone CLI Tool
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
cargo build --release
|
|
92
|
-
./target/release/rasgapdf --help
|
|
93
|
-
|
|
94
|
-
# ⚡ MODO 1: Coordenadas Brutas (Raw X/Y)
|
|
95
|
-
./target/release/rasgapdf sample.pdf --raw
|
|
96
|
-
./target/release/rasgapdf sample.pdf --raw --format text
|
|
97
|
-
./target/release/rasgapdf sample.pdf --raw --format csv
|
|
98
|
-
./target/release/rasgapdf sample.pdf --raw --format tsv
|
|
99
|
-
|
|
100
|
-
# 🎯 MODO 2: Estruturado (Hierárquico com Blocos e Tabelas)
|
|
101
|
-
./target/release/rasgapdf sample.pdf --pretty
|
|
102
|
-
./target/release/rasgapdf sample.pdf -o output.json
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## 🚀 Polyglot Quickstart
|
|
108
|
-
|
|
109
|
-
### 🐍 Python
|
|
110
|
-
```python
|
|
111
|
-
import rasgapdf
|
|
112
|
-
|
|
113
|
-
# ⚡ Modo 1: Coordenadas Brutas (Raw X/Y)
|
|
114
|
-
raw = rasgapdf.parse_raw("document.pdf")
|
|
115
|
-
print(f"Extraídos {raw['total_spans']} spans em {raw['parse_time_ms']:.2f} ms")
|
|
116
|
-
for s in raw["spans"]:
|
|
117
|
-
print(f"Pág {s['page']} | ({s['x0']}, {s['y0']}) -> {s['text']}")
|
|
118
|
-
|
|
119
|
-
# 🎯 Modo 2: Estruturado (Hierárquico)
|
|
120
|
-
doc = rasgapdf.parse_pdf("document.pdf", detect_tables=True)
|
|
121
|
-
for page in doc["pages"]:
|
|
122
|
-
for table in page["tables"]:
|
|
123
|
-
print("Tabela detectada:", table["rows"])
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 🟢 Node.js
|
|
127
|
-
```javascript
|
|
128
|
-
const rasgapdf = require('rasgapdf');
|
|
129
|
-
|
|
130
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
131
|
-
const raw = rasgapdf.parseRaw('document.pdf');
|
|
132
|
-
console.log(`Raw: ${raw.total_spans} spans em ${raw.parse_time_ms} ms`);
|
|
133
|
-
|
|
134
|
-
// 🎯 Modo 2: Estruturado
|
|
135
|
-
const doc = rasgapdf.parsePdf('document.pdf');
|
|
136
|
-
console.log(`Blocos de texto: ${doc.pages[0].text_blocks.length}`);
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 🔵 Go
|
|
140
|
-
```go
|
|
141
|
-
package main
|
|
142
|
-
|
|
143
|
-
import (
|
|
144
|
-
"fmt"
|
|
145
|
-
"github.com/messiasmartins/rasgapdf/bindings/go"
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
func main() {
|
|
149
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
150
|
-
raw, _ := rasgapdf.ParseRaw("document.pdf")
|
|
151
|
-
fmt.Printf("Raw: %d spans em %.2f ms\n", raw.TotalSpans, raw.ParseTimeMs)
|
|
152
|
-
|
|
153
|
-
// 🎯 Modo 2: Estruturado
|
|
154
|
-
opts := rasgapdf.DefaultOptions()
|
|
155
|
-
doc, _ := rasgapdf.ParseFile("document.pdf", &opts)
|
|
156
|
-
fmt.Printf("Estruturado: %d páginas\n", doc.TotalPages)
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### 🟣 C# / .NET 8
|
|
161
|
-
```csharp
|
|
162
|
-
using RasgaPdf;
|
|
163
|
-
|
|
164
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
165
|
-
var raw = SpatialPdf.ParseRaw("document.pdf");
|
|
166
|
-
Console.WriteLine($"Raw: {raw.TotalSpans} spans em {raw.ParseTimeMs} ms");
|
|
167
|
-
|
|
168
|
-
// 🎯 Modo 2: Estruturado
|
|
169
|
-
var doc = SpatialPdf.Parse("document.pdf");
|
|
170
|
-
Console.WriteLine($"Estruturado: {doc.TotalPages} páginas");
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## 🎨 Interactive Gradio Demo
|
|
176
|
-
|
|
177
|
-
We provide an interactive **visual spatial explorer** built with Gradio:
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
cd demo_gradio
|
|
181
|
-
pip install -r requirements.txt
|
|
182
|
-
python app.py
|
|
183
|
-
```
|
|
184
|
-
Acesse `http://localhost:7860` para:
|
|
185
|
-
- Inspecionar a **tabela interativa de Coordenadas Físicas (Raw X/Y)**.
|
|
186
|
-
- Visualizar os **bounding boxes translúcidos** sobrepostos à página do PDF.
|
|
187
|
-
- Analisar **tabelas detectadas** renderizadas em DataFrames.
|
|
188
|
-
- Exportar JSONs brutos ou estruturados.
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## 🤝 Contributing & Community
|
|
193
|
-
|
|
194
|
-
Contributions are what make the open-source community thrive!
|
|
195
|
-
- Read our [Contributing Guide](CONTRIBUTING.md) to get started.
|
|
196
|
-
- Adhere to our [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
## 📄 License
|
|
201
|
-
|
|
202
|
-
RasgaPDF is licensed under the [MIT License](LICENSE).
|
|
203
|
-
Copyright (c) 2026 Messias Martins.
|
rasgapdf-0.1.0/README.md
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
# ⚡ RasgaPDF
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
|
|
5
|
-
**The Blazing-Fast 2D Spatial PDF Parser powered by Pure Rust.**
|
|
6
|
-
*Extract exact physical coordinates (Raw X/Y) or structured blocks & tables at native hardware speeds.*
|
|
7
|
-
|
|
8
|
-
[](LICENSE)
|
|
9
|
-
[](Cargo.toml)
|
|
10
|
-
[](bindings/python)
|
|
11
|
-
[](bindings/nodejs)
|
|
12
|
-
[](bindings/go)
|
|
13
|
-
[](bindings/csharp)
|
|
14
|
-
[](https://huggingface.co/martinsmessias/rasgapdf)
|
|
15
|
-
|
|
16
|
-
[**Live Gradio Demo**](#-interactive-gradio-demo) • [**Quickstart**](#-quickstart) • [**Two Modes**](#-two-parsing-modes) • [**Architecture**](docs/ARCHITECTURE.md) • [**Spatial Schema**](docs/SCHEMA.md) • [**Contributing**](CONTRIBUTING.md)
|
|
17
|
-
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## 🎯 The Philosophy: Pure Spatial Parsing
|
|
23
|
-
|
|
24
|
-
Most PDF libraries make fragile guesses: they convert multi-column documents into flat, corrupted text streams, mangle tables, and strip away spatial geometry.
|
|
25
|
-
|
|
26
|
-
**RasgaPDF does one thing with uncompromising precision:**
|
|
27
|
-
It returns the **exact 2D physical spatial geometry** of the PDF.
|
|
28
|
-
|
|
29
|
-
- **Bounding Boxes Everywhere:** Every character, word span, line, block, and table has exact coordinates `[x0, y0, x1, y1]`.
|
|
30
|
-
- **Zero Lossy Guesswork:** No broken heuristics pretending to be Markdown. Your downstream LLMs, RAG pipelines, or OCR validators receive the true physical layout.
|
|
31
|
-
- **Microsecond Rayon Parallelism:** Multi-threaded page processing in pure Rust utilizing AVX2/AVX-512 SIMD.
|
|
32
|
-
- **Polyglot First:** Native C-ABI FFI bindings for **Python**, **Node.js**, **Go**, and **C# (.NET)**.
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## ⚡ Two Parsing Modes
|
|
37
|
-
|
|
38
|
-
RasgaPDF offers two distinct modes for different engineering needs:
|
|
39
|
-
|
|
40
|
-
### ⚡ Modo 1: Coordenadas Brutas (Raw X/Y Puro)
|
|
41
|
-
O retorno mais direto, bruto e rápido possível. Retorna exclusivamente a lista plana de coordenadas físicas de cada elemento desenhado na página, sem criar hierarquias de blocos ou overhead de tabelas:
|
|
42
|
-
- **Latência:** ~3 a 8 ms por página
|
|
43
|
-
- **Saídas suportadas:** JSON plano, Text formatado, TSV ou CSV
|
|
44
|
-
- **Uso ideal:** RAG espacial, visualizadores 2D, indexação vetorial, pipelines Unix com `awk`/`grep`.
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
[Pág. 1] (X0: 50.00, Y0: 67.00, X1: 244.00, Y1: 83.00) [12.0pt] A Revolução da Inteligência Artificial
|
|
48
|
-
[Pág. 1] (X0: 50.00, Y0: 103.00, X1: 478.00, Y1: 119.00) [12.0pt] A Inteligência Artificial (IA) tem transformado...
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### 🎯 Modo 2: Estruturado Hierárquico
|
|
52
|
-
Processa a geometria e agrupa elementos em parágrafos visuais (`blocks`), linhas (`lines`), spans de fonte e detecta matrizes de tabelas automaticamente via projeção horizontal de colunas:
|
|
53
|
-
- **Latência:** ~8 a 15 ms por página
|
|
54
|
-
- **Saída:** Árvore hierárquica `SpatialDocument` -> `pages` -> `text_blocks` -> `lines` -> `tables`.
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## ⚡ Performance Benchmark
|
|
59
|
-
|
|
60
|
-
Measured on Intel Core i7-1365U (10 Cores / 12 Threads, AVX2):
|
|
61
|
-
|
|
62
|
-
| Library / Tool | Language | Single Page | 50 Pages | Memory Footprint | Output Type |
|
|
63
|
-
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
64
|
-
| **⚡ RasgaPDF (Raw X/Y)** | **Rust (Native)** | **7.7 ms** | **95 ms** | **~14 MB** | **Flat Raw Coordinates** |
|
|
65
|
-
| **🚀 RasgaPDF (Structured)**| **Rust (Native)** | **8.5 ms** | **142 ms** | **~18 MB** | **Spatial Blocks & Tables** |
|
|
66
|
-
| PyMuPDF (`fitz`) | C / Python | 28.0 ms | 620 ms | ~45 MB | Text / Pixmap |
|
|
67
|
-
| `pdfplumber` | Python | 410.0 ms | 9,800 ms | ~140 MB | Python dicts |
|
|
68
|
-
| `pypdf` | Python | 95.0 ms | 2,100 ms | ~85 MB | Flat text string |
|
|
69
|
-
| Apache Tika | Java | 650.0 ms | 12,400 ms | ~320 MB | XHTML |
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## 💻 Standalone CLI Tool
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
cargo build --release
|
|
77
|
-
./target/release/rasgapdf --help
|
|
78
|
-
|
|
79
|
-
# ⚡ MODO 1: Coordenadas Brutas (Raw X/Y)
|
|
80
|
-
./target/release/rasgapdf sample.pdf --raw
|
|
81
|
-
./target/release/rasgapdf sample.pdf --raw --format text
|
|
82
|
-
./target/release/rasgapdf sample.pdf --raw --format csv
|
|
83
|
-
./target/release/rasgapdf sample.pdf --raw --format tsv
|
|
84
|
-
|
|
85
|
-
# 🎯 MODO 2: Estruturado (Hierárquico com Blocos e Tabelas)
|
|
86
|
-
./target/release/rasgapdf sample.pdf --pretty
|
|
87
|
-
./target/release/rasgapdf sample.pdf -o output.json
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## 🚀 Polyglot Quickstart
|
|
93
|
-
|
|
94
|
-
### 🐍 Python
|
|
95
|
-
```python
|
|
96
|
-
import rasgapdf
|
|
97
|
-
|
|
98
|
-
# ⚡ Modo 1: Coordenadas Brutas (Raw X/Y)
|
|
99
|
-
raw = rasgapdf.parse_raw("document.pdf")
|
|
100
|
-
print(f"Extraídos {raw['total_spans']} spans em {raw['parse_time_ms']:.2f} ms")
|
|
101
|
-
for s in raw["spans"]:
|
|
102
|
-
print(f"Pág {s['page']} | ({s['x0']}, {s['y0']}) -> {s['text']}")
|
|
103
|
-
|
|
104
|
-
# 🎯 Modo 2: Estruturado (Hierárquico)
|
|
105
|
-
doc = rasgapdf.parse_pdf("document.pdf", detect_tables=True)
|
|
106
|
-
for page in doc["pages"]:
|
|
107
|
-
for table in page["tables"]:
|
|
108
|
-
print("Tabela detectada:", table["rows"])
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### 🟢 Node.js
|
|
112
|
-
```javascript
|
|
113
|
-
const rasgapdf = require('rasgapdf');
|
|
114
|
-
|
|
115
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
116
|
-
const raw = rasgapdf.parseRaw('document.pdf');
|
|
117
|
-
console.log(`Raw: ${raw.total_spans} spans em ${raw.parse_time_ms} ms`);
|
|
118
|
-
|
|
119
|
-
// 🎯 Modo 2: Estruturado
|
|
120
|
-
const doc = rasgapdf.parsePdf('document.pdf');
|
|
121
|
-
console.log(`Blocos de texto: ${doc.pages[0].text_blocks.length}`);
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### 🔵 Go
|
|
125
|
-
```go
|
|
126
|
-
package main
|
|
127
|
-
|
|
128
|
-
import (
|
|
129
|
-
"fmt"
|
|
130
|
-
"github.com/messiasmartins/rasgapdf/bindings/go"
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
func main() {
|
|
134
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
135
|
-
raw, _ := rasgapdf.ParseRaw("document.pdf")
|
|
136
|
-
fmt.Printf("Raw: %d spans em %.2f ms\n", raw.TotalSpans, raw.ParseTimeMs)
|
|
137
|
-
|
|
138
|
-
// 🎯 Modo 2: Estruturado
|
|
139
|
-
opts := rasgapdf.DefaultOptions()
|
|
140
|
-
doc, _ := rasgapdf.ParseFile("document.pdf", &opts)
|
|
141
|
-
fmt.Printf("Estruturado: %d páginas\n", doc.TotalPages)
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### 🟣 C# / .NET 8
|
|
146
|
-
```csharp
|
|
147
|
-
using RasgaPdf;
|
|
148
|
-
|
|
149
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
150
|
-
var raw = SpatialPdf.ParseRaw("document.pdf");
|
|
151
|
-
Console.WriteLine($"Raw: {raw.TotalSpans} spans em {raw.ParseTimeMs} ms");
|
|
152
|
-
|
|
153
|
-
// 🎯 Modo 2: Estruturado
|
|
154
|
-
var doc = SpatialPdf.Parse("document.pdf");
|
|
155
|
-
Console.WriteLine($"Estruturado: {doc.TotalPages} páginas");
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## 🎨 Interactive Gradio Demo
|
|
161
|
-
|
|
162
|
-
We provide an interactive **visual spatial explorer** built with Gradio:
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
cd demo_gradio
|
|
166
|
-
pip install -r requirements.txt
|
|
167
|
-
python app.py
|
|
168
|
-
```
|
|
169
|
-
Acesse `http://localhost:7860` para:
|
|
170
|
-
- Inspecionar a **tabela interativa de Coordenadas Físicas (Raw X/Y)**.
|
|
171
|
-
- Visualizar os **bounding boxes translúcidos** sobrepostos à página do PDF.
|
|
172
|
-
- Analisar **tabelas detectadas** renderizadas em DataFrames.
|
|
173
|
-
- Exportar JSONs brutos ou estruturados.
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## 🤝 Contributing & Community
|
|
178
|
-
|
|
179
|
-
Contributions are what make the open-source community thrive!
|
|
180
|
-
- Read our [Contributing Guide](CONTRIBUTING.md) to get started.
|
|
181
|
-
- Adhere to our [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## 📄 License
|
|
186
|
-
|
|
187
|
-
RasgaPDF is licensed under the [MIT License](LICENSE).
|
|
188
|
-
Copyright (c) 2026 Messias Martins.
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: rasgapdf
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Ultra-fast 2D spatial PDF parser powered by Rust
|
|
5
|
-
Author: Messias Martins
|
|
6
|
-
Project-URL: Homepage, https://github.com/messiasmartins/rasgapdf
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/messiasmartins/rasgapdf/issues
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Rust
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
-
Classifier: Topic :: Text Processing :: General
|
|
13
|
-
Requires-Python: >=3.8
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
|
-
# ⚡ RasgaPDF
|
|
17
|
-
|
|
18
|
-
<div align="center">
|
|
19
|
-
|
|
20
|
-
**The Blazing-Fast 2D Spatial PDF Parser powered by Pure Rust.**
|
|
21
|
-
*Extract exact physical coordinates (Raw X/Y) or structured blocks & tables at native hardware speeds.*
|
|
22
|
-
|
|
23
|
-
[](LICENSE)
|
|
24
|
-
[](Cargo.toml)
|
|
25
|
-
[](bindings/python)
|
|
26
|
-
[](bindings/nodejs)
|
|
27
|
-
[](bindings/go)
|
|
28
|
-
[](bindings/csharp)
|
|
29
|
-
[](https://huggingface.co/martinsmessias/rasgapdf)
|
|
30
|
-
|
|
31
|
-
[**Live Gradio Demo**](#-interactive-gradio-demo) • [**Quickstart**](#-quickstart) • [**Two Modes**](#-two-parsing-modes) • [**Architecture**](docs/ARCHITECTURE.md) • [**Spatial Schema**](docs/SCHEMA.md) • [**Contributing**](CONTRIBUTING.md)
|
|
32
|
-
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 🎯 The Philosophy: Pure Spatial Parsing
|
|
38
|
-
|
|
39
|
-
Most PDF libraries make fragile guesses: they convert multi-column documents into flat, corrupted text streams, mangle tables, and strip away spatial geometry.
|
|
40
|
-
|
|
41
|
-
**RasgaPDF does one thing with uncompromising precision:**
|
|
42
|
-
It returns the **exact 2D physical spatial geometry** of the PDF.
|
|
43
|
-
|
|
44
|
-
- **Bounding Boxes Everywhere:** Every character, word span, line, block, and table has exact coordinates `[x0, y0, x1, y1]`.
|
|
45
|
-
- **Zero Lossy Guesswork:** No broken heuristics pretending to be Markdown. Your downstream LLMs, RAG pipelines, or OCR validators receive the true physical layout.
|
|
46
|
-
- **Microsecond Rayon Parallelism:** Multi-threaded page processing in pure Rust utilizing AVX2/AVX-512 SIMD.
|
|
47
|
-
- **Polyglot First:** Native C-ABI FFI bindings for **Python**, **Node.js**, **Go**, and **C# (.NET)**.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## ⚡ Two Parsing Modes
|
|
52
|
-
|
|
53
|
-
RasgaPDF offers two distinct modes for different engineering needs:
|
|
54
|
-
|
|
55
|
-
### ⚡ Modo 1: Coordenadas Brutas (Raw X/Y Puro)
|
|
56
|
-
O retorno mais direto, bruto e rápido possível. Retorna exclusivamente a lista plana de coordenadas físicas de cada elemento desenhado na página, sem criar hierarquias de blocos ou overhead de tabelas:
|
|
57
|
-
- **Latência:** ~3 a 8 ms por página
|
|
58
|
-
- **Saídas suportadas:** JSON plano, Text formatado, TSV ou CSV
|
|
59
|
-
- **Uso ideal:** RAG espacial, visualizadores 2D, indexação vetorial, pipelines Unix com `awk`/`grep`.
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
[Pág. 1] (X0: 50.00, Y0: 67.00, X1: 244.00, Y1: 83.00) [12.0pt] A Revolução da Inteligência Artificial
|
|
63
|
-
[Pág. 1] (X0: 50.00, Y0: 103.00, X1: 478.00, Y1: 119.00) [12.0pt] A Inteligência Artificial (IA) tem transformado...
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 🎯 Modo 2: Estruturado Hierárquico
|
|
67
|
-
Processa a geometria e agrupa elementos em parágrafos visuais (`blocks`), linhas (`lines`), spans de fonte e detecta matrizes de tabelas automaticamente via projeção horizontal de colunas:
|
|
68
|
-
- **Latência:** ~8 a 15 ms por página
|
|
69
|
-
- **Saída:** Árvore hierárquica `SpatialDocument` -> `pages` -> `text_blocks` -> `lines` -> `tables`.
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## ⚡ Performance Benchmark
|
|
74
|
-
|
|
75
|
-
Measured on Intel Core i7-1365U (10 Cores / 12 Threads, AVX2):
|
|
76
|
-
|
|
77
|
-
| Library / Tool | Language | Single Page | 50 Pages | Memory Footprint | Output Type |
|
|
78
|
-
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
79
|
-
| **⚡ RasgaPDF (Raw X/Y)** | **Rust (Native)** | **7.7 ms** | **95 ms** | **~14 MB** | **Flat Raw Coordinates** |
|
|
80
|
-
| **🚀 RasgaPDF (Structured)**| **Rust (Native)** | **8.5 ms** | **142 ms** | **~18 MB** | **Spatial Blocks & Tables** |
|
|
81
|
-
| PyMuPDF (`fitz`) | C / Python | 28.0 ms | 620 ms | ~45 MB | Text / Pixmap |
|
|
82
|
-
| `pdfplumber` | Python | 410.0 ms | 9,800 ms | ~140 MB | Python dicts |
|
|
83
|
-
| `pypdf` | Python | 95.0 ms | 2,100 ms | ~85 MB | Flat text string |
|
|
84
|
-
| Apache Tika | Java | 650.0 ms | 12,400 ms | ~320 MB | XHTML |
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## 💻 Standalone CLI Tool
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
cargo build --release
|
|
92
|
-
./target/release/rasgapdf --help
|
|
93
|
-
|
|
94
|
-
# ⚡ MODO 1: Coordenadas Brutas (Raw X/Y)
|
|
95
|
-
./target/release/rasgapdf sample.pdf --raw
|
|
96
|
-
./target/release/rasgapdf sample.pdf --raw --format text
|
|
97
|
-
./target/release/rasgapdf sample.pdf --raw --format csv
|
|
98
|
-
./target/release/rasgapdf sample.pdf --raw --format tsv
|
|
99
|
-
|
|
100
|
-
# 🎯 MODO 2: Estruturado (Hierárquico com Blocos e Tabelas)
|
|
101
|
-
./target/release/rasgapdf sample.pdf --pretty
|
|
102
|
-
./target/release/rasgapdf sample.pdf -o output.json
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
---
|
|
106
|
-
|
|
107
|
-
## 🚀 Polyglot Quickstart
|
|
108
|
-
|
|
109
|
-
### 🐍 Python
|
|
110
|
-
```python
|
|
111
|
-
import rasgapdf
|
|
112
|
-
|
|
113
|
-
# ⚡ Modo 1: Coordenadas Brutas (Raw X/Y)
|
|
114
|
-
raw = rasgapdf.parse_raw("document.pdf")
|
|
115
|
-
print(f"Extraídos {raw['total_spans']} spans em {raw['parse_time_ms']:.2f} ms")
|
|
116
|
-
for s in raw["spans"]:
|
|
117
|
-
print(f"Pág {s['page']} | ({s['x0']}, {s['y0']}) -> {s['text']}")
|
|
118
|
-
|
|
119
|
-
# 🎯 Modo 2: Estruturado (Hierárquico)
|
|
120
|
-
doc = rasgapdf.parse_pdf("document.pdf", detect_tables=True)
|
|
121
|
-
for page in doc["pages"]:
|
|
122
|
-
for table in page["tables"]:
|
|
123
|
-
print("Tabela detectada:", table["rows"])
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 🟢 Node.js
|
|
127
|
-
```javascript
|
|
128
|
-
const rasgapdf = require('rasgapdf');
|
|
129
|
-
|
|
130
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
131
|
-
const raw = rasgapdf.parseRaw('document.pdf');
|
|
132
|
-
console.log(`Raw: ${raw.total_spans} spans em ${raw.parse_time_ms} ms`);
|
|
133
|
-
|
|
134
|
-
// 🎯 Modo 2: Estruturado
|
|
135
|
-
const doc = rasgapdf.parsePdf('document.pdf');
|
|
136
|
-
console.log(`Blocos de texto: ${doc.pages[0].text_blocks.length}`);
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### 🔵 Go
|
|
140
|
-
```go
|
|
141
|
-
package main
|
|
142
|
-
|
|
143
|
-
import (
|
|
144
|
-
"fmt"
|
|
145
|
-
"github.com/messiasmartins/rasgapdf/bindings/go"
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
func main() {
|
|
149
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
150
|
-
raw, _ := rasgapdf.ParseRaw("document.pdf")
|
|
151
|
-
fmt.Printf("Raw: %d spans em %.2f ms\n", raw.TotalSpans, raw.ParseTimeMs)
|
|
152
|
-
|
|
153
|
-
// 🎯 Modo 2: Estruturado
|
|
154
|
-
opts := rasgapdf.DefaultOptions()
|
|
155
|
-
doc, _ := rasgapdf.ParseFile("document.pdf", &opts)
|
|
156
|
-
fmt.Printf("Estruturado: %d páginas\n", doc.TotalPages)
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### 🟣 C# / .NET 8
|
|
161
|
-
```csharp
|
|
162
|
-
using RasgaPdf;
|
|
163
|
-
|
|
164
|
-
// ⚡ Modo 1: Coordenadas Brutas
|
|
165
|
-
var raw = SpatialPdf.ParseRaw("document.pdf");
|
|
166
|
-
Console.WriteLine($"Raw: {raw.TotalSpans} spans em {raw.ParseTimeMs} ms");
|
|
167
|
-
|
|
168
|
-
// 🎯 Modo 2: Estruturado
|
|
169
|
-
var doc = SpatialPdf.Parse("document.pdf");
|
|
170
|
-
Console.WriteLine($"Estruturado: {doc.TotalPages} páginas");
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## 🎨 Interactive Gradio Demo
|
|
176
|
-
|
|
177
|
-
We provide an interactive **visual spatial explorer** built with Gradio:
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
cd demo_gradio
|
|
181
|
-
pip install -r requirements.txt
|
|
182
|
-
python app.py
|
|
183
|
-
```
|
|
184
|
-
Acesse `http://localhost:7860` para:
|
|
185
|
-
- Inspecionar a **tabela interativa de Coordenadas Físicas (Raw X/Y)**.
|
|
186
|
-
- Visualizar os **bounding boxes translúcidos** sobrepostos à página do PDF.
|
|
187
|
-
- Analisar **tabelas detectadas** renderizadas em DataFrames.
|
|
188
|
-
- Exportar JSONs brutos ou estruturados.
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## 🤝 Contributing & Community
|
|
193
|
-
|
|
194
|
-
Contributions are what make the open-source community thrive!
|
|
195
|
-
- Read our [Contributing Guide](CONTRIBUTING.md) to get started.
|
|
196
|
-
- Adhere to our [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
## 📄 License
|
|
201
|
-
|
|
202
|
-
RasgaPDF is licensed under the [MIT License](LICENSE).
|
|
203
|
-
Copyright (c) 2026 Messias Martins.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|