100 lines
3.9 KiB
Python
100 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Парсинг регламента через Unstructured API.
|
|
Делает один проход (strategy=hi_res) и разделяет элементы на текст и таблицы.
|
|
"""
|
|
import json
|
|
import re
|
|
import requests
|
|
from pathlib import Path
|
|
|
|
# === НАСТРОЙКИ ===
|
|
UNSTRUCTURED_API = "http://192.168.1.103:8005/general/v0/general"
|
|
PDF_PATH = "/opt/documents_xk/АОХКСибцем/07 Служба Вице-президента по экономике и финансам/ДИТ/02 Регламенты деятельности/08 Положение Управление ИТ-инцидентами от 20.02.2024 № ПОЛ-123-2.pdf"
|
|
OUTPUT_PATH = "/opt/okf-regulations/concepts/pol123_parsed.json"
|
|
|
|
|
|
def parse_document(pdf_path: str) -> dict:
|
|
"""Отправляет PDF в API (hi_res) и возвращает рассортированные данные."""
|
|
print(f" Отправка файла {Path(pdf_path).name} в Unstructured API (hi_res)...")
|
|
|
|
with open(pdf_path, "rb") as f:
|
|
files = {"files": (Path(pdf_path).name, f, "application/pdf")}
|
|
data = {
|
|
"strategy": "hi_res",
|
|
"coordinates": "true"
|
|
}
|
|
|
|
try:
|
|
response = requests.post(UNSTRUCTURED_API, files=files, data=data, timeout=300)
|
|
response.raise_for_status()
|
|
except requests.exceptions.RequestException as e:
|
|
print(f" ❌ Ошибка Unstructured API: {e}")
|
|
return {"text": [], "tables": []}
|
|
|
|
elements = response.json()
|
|
if isinstance(elements, dict):
|
|
elements = elements.get("elements", [])
|
|
|
|
text_elements = []
|
|
real_tables = []
|
|
|
|
print(" Сортировка и фильтрация элементов...")
|
|
for el in elements:
|
|
el_type = el.get("type")
|
|
|
|
if el_type == "Table":
|
|
meta = el.get("metadata", {})
|
|
html = meta.get("text_as_html", "")
|
|
|
|
# Строгий фильтр на наличие HTML-таблицы
|
|
if html and "<table" in html.lower():
|
|
row_count = len(re.findall(r'<tr[^>]*>', html, re.IGNORECASE)) if html else None
|
|
col_count = len(re.findall(r'<td[^>]*>|<th[^>]*>', html[:500], re.IGNORECASE)) if html else None
|
|
|
|
real_tables.append({
|
|
"page": meta.get("page_number"),
|
|
"text": el.get("text", ""),
|
|
"html": html,
|
|
"row_count": row_count,
|
|
"col_count": col_count,
|
|
})
|
|
else:
|
|
# Если таблица оказалась фейковой, отправляем её текст в общий котел
|
|
text_elements.append(el)
|
|
else:
|
|
# Всё остальное (Title, NarrativeText, ListItem и т.д.)
|
|
text_elements.append(el)
|
|
|
|
return {"text": text_elements, "tables": real_tables}
|
|
|
|
|
|
def main():
|
|
print("=" * 60)
|
|
print(f"📄 Парсинг документа: {Path(PDF_PATH).name}")
|
|
print("=" * 60)
|
|
|
|
parsed_data = parse_document(PDF_PATH)
|
|
|
|
print(f"\n[Итоги]")
|
|
print(f" ✅ Получено текстовых элементов: {len(parsed_data['text'])}")
|
|
print(f" ✅ Найдено валидных таблиц: {len(parsed_data['tables'])}")
|
|
|
|
result = {
|
|
"document": "ПОЛ-123",
|
|
"title": "Положение Управление ИТ-инцидентами от 20.02.2024 № ПОЛ-123-2",
|
|
"text": parsed_data["text"],
|
|
"tables": parsed_data["tables"],
|
|
"metadata": {
|
|
"unstructured_api": UNSTRUCTURED_API,
|
|
"strategy": "hi_res",
|
|
"timestamp": "2026-07-06",
|
|
},
|
|
}
|
|
|
|
Path(OUTPUT_PATH).write_text(json.dumps(result, ensure_ascii=False, indent=2))
|
|
print(f"\n✅ Сохранено в {OUTPUT_PATH}")
|
|
print("=" * 60)
|
|
|
|
if __name__ == "__main__":
|
|
main() |