128 lines
4.8 KiB
Python
128 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Парсинг ПОЛ-177 через Unstructured API:
|
|
- Текст: Unstructured API (192.168.1.103:8005)
|
|
- Таблицы: Unstructured API (element_type=Table, strategy=hi_res)
|
|
|
|
Сохраняет результат в /opt/okf-regulations/concepts/pol177_parsed.json
|
|
"""
|
|
import json
|
|
import subprocess
|
|
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 fetch_unstructured(pdf_path: str, strategy: str = "hi_res", element_type: str = None) -> list[dict]:
|
|
"""Получаем элементы из Unstructured API.
|
|
|
|
Args:
|
|
pdf_path: путь к PDF
|
|
strategy: hi_res для таблиц, fast для текста
|
|
element_type: фильтр по типу (None = все, 'Table' = только таблицы)
|
|
"""
|
|
cmd = [
|
|
"curl", "-X", "POST", UNSTRUCTURED_API,
|
|
"-F", f"files=@{pdf_path}",
|
|
"-F", f"strategy={strategy}",
|
|
"-F", "output_format=application/json",
|
|
"-F", "coordinates=true",
|
|
]
|
|
if element_type:
|
|
cmd.extend(["-F", f"element_types=[{element_type}]"])
|
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
print(f" ❌ Unstructured API error: {result.stderr}")
|
|
return []
|
|
data = json.loads(result.stdout)
|
|
if isinstance(data, list):
|
|
return data
|
|
return data.get("elements", [])
|
|
|
|
def extract_tables(pdf_path: str) -> list[dict]:
|
|
"""Извлекаем таблицы через Unstructured API и фильтруем по типу + HTML."""
|
|
print(" Запрос всех элементов через Unstructured API (strategy=hi_res)...")
|
|
elements = fetch_unstructured(pdf_path, strategy="hi_res", element_type=None)
|
|
|
|
real_tables = []
|
|
for el in elements:
|
|
# Фильтр 1: тип должен быть Table
|
|
if el.get("type") != "Table":
|
|
continue
|
|
|
|
meta = el.get("metadata", {})
|
|
text = el.get("text", "")
|
|
html = meta.get("text_as_html", "")
|
|
|
|
# Фильтр 2: должен быть HTML-представление (настоящая таблица)
|
|
if not html or "<table" not in html.lower():
|
|
continue
|
|
|
|
# Извлекаем row/col из HTML
|
|
row_count = None
|
|
col_count = None
|
|
if html:
|
|
import re
|
|
trs = re.findall(r'<tr[^>]*>', html, re.IGNORECASE)
|
|
first_tr = re.findall(r'<td[^>]*>|<th[^>]*>', html[:500], re.IGNORECASE)
|
|
if trs:
|
|
row_count = len(trs)
|
|
if first_tr:
|
|
col_count = len(first_tr)
|
|
|
|
table_data = {
|
|
"page": meta.get("page_number"),
|
|
"text": text,
|
|
"html": html,
|
|
"row_count": row_count,
|
|
"col_count": col_count,
|
|
}
|
|
real_tables.append(table_data)
|
|
|
|
return real_tables
|
|
|
|
def extract_text(pdf_path: str) -> list[dict]:
|
|
"""Извлекаем текст через Unstructured API (strategy=fast)."""
|
|
print(" Запрос текста через Unstructured API (strategy=fast)...")
|
|
elements = fetch_unstructured(pdf_path, strategy="fast")
|
|
return elements
|
|
|
|
def main():
|
|
print("=" * 60)
|
|
print("📄 Парсинг ПОЛ-177")
|
|
print("=" * 60)
|
|
|
|
# 1. Текст
|
|
print("\n[1/3] Извлечение текста (strategy=fast)...")
|
|
text_elements = extract_text(PDF_PATH)
|
|
print(f" ✅ Получено {len(text_elements)} элементов")
|
|
|
|
# 2. Таблицы
|
|
print("\n[2/3] Извлечение таблиц (element_type=Table)...")
|
|
tables = extract_tables(PDF_PATH)
|
|
print(f" ✅ Найдено {len(tables)} таблиц")
|
|
|
|
# 3. Сохраняем результат
|
|
result = {
|
|
"document": "ПОЛ-123",
|
|
"title": "Положение Управление ИТ-инцидентами от 20.02.2024 № ПОЛ-123-2",
|
|
"text": text_elements,
|
|
"tables": tables,
|
|
"metadata": {
|
|
"unstructured_api": UNSTRUCTURED_API,
|
|
"strategy_text": "fast",
|
|
"strategy_tables": "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()
|