Update parse_pol177.py: use Unstructured API for tables, remove pypdf
This commit is contained in:
+115
-61
@@ -1,73 +1,127 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Parse PDF document using unstructured-api on 192.168.1.103.
|
||||
Uses maximum quality settings (hi_res + yolox model).
|
||||
Saves parsed JSON to /tmp/pol177_parsed.json.
|
||||
Парсинг ПОЛ-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 requests
|
||||
import json
|
||||
import sys
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
PDF_PATH = "/opt/documents_xk/АОХКСибцем/07 Служба Вице-президента по экономике и финансам/ДИТ/02 Регламенты деятельности/10 Положение Хранение электронных документов от 03.04.2024 № ПОЛ-177.pdf"
|
||||
API_URL = "http://192.168.1.103:8005/general/v0/general"
|
||||
# === НАСТРОЙКИ ===
|
||||
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_pdf():
|
||||
print("Parsing PDF with maximum quality (hi_res + yolox)...")
|
||||
def fetch_unstructured(pdf_path: str, strategy: str = "hi_res", element_type: str = None) -> list[dict]:
|
||||
"""Получаем элементы из Unstructured API.
|
||||
|
||||
# Maximum quality parameters
|
||||
form_data = {
|
||||
'strategy': 'hi_res',
|
||||
'hi_res_model_name': 'yolox',
|
||||
'pdf_infer_table_structure': 'true',
|
||||
'extract_images': 'true',
|
||||
'extract_image_block_types': '["image", "table"]',
|
||||
}
|
||||
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}]"])
|
||||
|
||||
with open(PDF_PATH, 'rb') as f:
|
||||
# Note: 'files' (plural) - API expects list of UploadFile
|
||||
files = {'files': f}
|
||||
response = requests.post(API_URL, files=files, data=form_data)
|
||||
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", [])
|
||||
|
||||
if response.status_code != 200:
|
||||
print(f"ERROR: API returned {response.status_code}: {response.text[:500]}")
|
||||
sys.exit(1)
|
||||
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)
|
||||
|
||||
result = response.json()
|
||||
|
||||
# API returns array directly, not {"elements": [...]}
|
||||
if isinstance(result, list):
|
||||
elements = result
|
||||
else:
|
||||
elements = result.get('elements', [])
|
||||
|
||||
print(f"Extracted {len(elements)} elements")
|
||||
|
||||
# Add page numbers
|
||||
for i, el in enumerate(elements):
|
||||
if 'page_number' in el.get('metadata', {}):
|
||||
el['page_number'] = el['metadata']['page_number']
|
||||
else:
|
||||
el['page_number'] = i + 1
|
||||
|
||||
# Save to JSON
|
||||
output = {
|
||||
'filename': '10 Положение Хранение электронных документов от 03.04.2024 № ПОЛ-177.pdf',
|
||||
'total_elements': len(elements),
|
||||
'elements': elements
|
||||
}
|
||||
|
||||
with open('/tmp/pol177_parsed.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(output, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"Saved {len(elements)} elements to /tmp/pol177_parsed.json")
|
||||
|
||||
# Stats
|
||||
types = {}
|
||||
real_tables = []
|
||||
for el in elements:
|
||||
t = el.get('type', 'Unknown')
|
||||
types[t] = types.get(t, 0) + 1
|
||||
print(f"Element types: {types}")
|
||||
# Фильтр 1: тип должен быть Table
|
||||
if el.get("type") != "Table":
|
||||
continue
|
||||
|
||||
if __name__ == '__main__':
|
||||
parse_pdf()
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user