English translation is not available yet. Showing Russian content.
Как вы парсите сложные PDF с таблицами и графиками (не просто текст)?
Краткий тезис
Парсинг сложных PDF с таблицами и графиками — это многоэтапный процесс, выходящий за рамки простого извлечения текста. Он включает детекцию и распознавание таблиц (с помощью моделей вроде Table Transformer или инструментов Unstructured.io), извлечение числовых данных из графиков через OCR и VL-LLM, а также понимание структуры документа (заголовки, колонки, сноски) с помощью LayoutLMv3. Конечная цель — получить семантический HTML или структурированный JSON, сохраняющий иерархию и взаимосвязи элементов, пригодный для дальнейшего использования в RAG-системах.
1. Термины и базовые понятия
- PDF (Portable Document Format) — формат, предназначенный для представления документов в фиксированном макете. Сложность парсинга возникает из-за того, что PDF не хранит логическую структуру (заголовки, абзацы, таблицы) — только позиции символов и графические примитивы.
- OCR (Optical Character Recognition) — технология распознавания текста на изображениях. Необходима для сканированных PDF (не текстовых слоёв).
- LayoutLMv3 — модель от Microsoft для понимания макета документа. Она объединяет текст, изображения и координаты блоков, позволяя классифицировать элементы (заголовок, таблица, сноска, подпись к рисунку).
- Table Transformer (TATR) — модель на основе DETR (Detection Transformer), обученная для детекции и распознавания таблиц в документах. Позволяет выделить границы таблиц и ячеек.
- VL-LLM (Vision-Language Large Language Model) — LLM|мультимодальная LLM, способная обрабатывать изображения и текст. Примеры: GPT-4V, LLaVA, Qwen-VL. Используется для описания графиков и извлечения числовых значений.
2. Обзор инструментов для парсинга PDF
| Инструмент | Тип | Сильные стороны | Ограничения |
|---|---|---|---|
| PyMuPDF (fitz) | Библиотека Python | Быстрый, извлекает текст с координатами, поддерживает таблицы (через get_table()) | Сложные таблицы (объединённые ячейки) могут быть неверно распознаны |
| pdfplumber | Библиотека Python | Хорошо извлекает таблицы с настройками (table_settings), работает с текстовыми PDF | Медленнее PyMuPDF, не подходит для сканов |
| Camelot | Библиотека Python | Специализируется на таблицах: два режима (Lattice и Stream) | Требует текстовый PDF, не обрабатывает графики |
| Tabula | Java-утилита / Python wrapper | Хорош для таблиц с чёткими линиями | Зависит от Java, не для сканов |
| Unstructured.io | Платформа / библиотека | Модульный пайплайн: детекция таблиц, изображений, заголовков; поддержка OCR через Tesseract | Требует настройки, может быть избыточен для простых PDF |
| Table Transformer (TATR) | Модель (Hugging Face) | State-of-the-art детекция и распознавание таблиц на изображениях | Требует GPU, нужна постобработка |
| LayoutLMv3 | Модель (Hugging Face) | Понимание структуры документа (классификация блоков) | Не извлекает таблицы напрямую, используется как часть пайплайна |
| Donut / Nougat | Модели (Hugging Face) | End-to-end распознавание документа (включая математику) | Требуют много ресурсов, не всегда точны для сложных макетов |
3. Детекция и извлечение таблиц
3.1. Подходы
- Правила и эвристики (Camelot, pdfplumber): ищут линии сетки или пробелы между колонками. Работают только на текстовых PDF с чёткой структурой.
- Глубокое обучение (TATR, TableNet): детектируют таблицы на изображении страницы, затем распознают ячейки. Работают на сканах и сложных макетах.
- Гибридный (Unstructured.io): сначала детекция таблиц через TATR, затем извлечение текста из ячеек с помощью OCR (Tesseract) или встроенного парсера.
3.2. Пример пайплайна с TATR
from transformers import TableTransformerForObjectDetection, TableTransformerImageProcessor
from PIL import Image
import torch
# Загрузка модели
processor = TableTransformerImageProcessor.from_pretrained("microsoft/table-transformer-detection")
model = TableTransformerForObjectDetection.from_pretrained("microsoft/table-transformer-detection")
# Открыть страницу PDF как изображение (предварительно конвертировать)
image = Image.open("page.png")
inputs = processor(images=image, return_tensors="pt")
# Детекция таблиц
with torch.no_grad():
outputs = model(**inputs)
# Постобработка: получить bounding boxes таблиц
target_sizes = torch.tensor([image.size[::-1]])
results = processor.post_process_object_detection(outputs, threshold=0.7, target_sizes=target_sizes)[0]
for box, score, label in zip(results["boxes"], results["scores"], results["labels"]):
if model.config.id2label[label.item()] == "table":
# Вырезать область таблицы
table_region = image.crop(box.tolist())
# Далее — распознавание структуры таблицы (структурная модель TATR)
3.3. Форматы вывода таблиц
- HTML — сохраняет структуру строк и столбцов, легко встраивается в веб-интерфейсы.
- Markdown — компактный, читаемый, подходит для LLM.
- JSON — максимально гибкий, можно хранить метаданные (объединённые ячейки, стили).
Пример вывода в HTML:
<table>
<thead>
<tr><th>Год</th><th>Доход</th><th>Расход</th></tr>
</thead>
<tbody>
<tr><td>2023</td><td>100</td><td>80</td></tr>
<tr><td>2024</td><td>120</td><td>90</td></tr>
</tbody>
</table>
4. Извлечение графиков
Графики (линейные, столбчатые, круговые) — это изображения, из которых нужно получить числовые данные и семантическое описание.
4.1. Этапы
- Детекция графика на странице (можно использовать LayoutLMv3 или детектор изображений).
- Вырезание области графика.
- OCR числовых значений на осях и внутри графика (Tesseract, PaddleOCR).
- Извлечение легенды (также OCR + NLP для сопоставления меток).
- Генерация текстового описания с помощью VL-LLM.
4.2. Пример с VL-LLM (GPT-4V)
import base64
from openai import OpenAI
client = OpenAI()
def describe_chart(image_path):
with open(image_path, "rb") as f:
base64_image = base64.b64encode(f.read()).decode("utf-8")
response = client.chat.completions.create(
model="gpt-4-vision-preview",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Опиши этот график: какие оси, какие значения, тренды. Верни структурированный JSON с ключами: title, x_label, y_label, data_points (список {x, y, label}), legend."},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_image}"}}
]
}
],
max_tokens=1000
)
return response.choices[0].message.content
4.3. Альтернатива: специализированные модели
- ChartQA — датасет и модель для вопросов по графикам.
- PlotQA — генерация табличных данных из графиков.
- DePlot — модель Google, преобразующая график в таблицу.
5. Понимание структуры документа с LayoutLMv3
LayoutLMv3 позволяет классифицировать каждый текстовый блок на странице: заголовок, абзац, таблица, рисунок, сноска, номер страницы и т.д. Это критически важно для восстановления иерархии.
5.1. Пример использования
from [transformers](/wiki/transformers) import LayoutLMv3Processor, LayoutLMv3ForTokenClassification
from PIL import [Image](/wiki/Image)
import torch
processor = LayoutLMv3Processor.from_pretrained("microsoft/layoutlmv3-base")
[model](/wiki/model) = LayoutLMv3ForTokenClassification.from_pretrained("microsoft/layoutlmv3-base")
[image](/wiki/Image) = [Image](/wiki/Image).open("page.png")
# Предположим, у нас есть OCR-боксы и текст
encoding = processor([image](/wiki/Image), [text](/wiki/text)="...", boxes=[541](/answers/541)
---
## Навигация
- Предыдущий: [541](/answers/541)
- Следующий: [543](/answers/543)
- Индекс: [00. Индекс разборов](/answers)