#!/usr/bin/env python3 """ Универсальный скрипт для улучшения MD-файлов документов АО «ХК «Сибцем». Выполняется на сервере 192.168.1.106. Применяет паттерны: 1. Удаляет футеры страниц 2. Форматирует блок "УТВЕРЖДАЮ" 3. Выравнивает иерархию заголовков 4. Объединяет таблицы терминов 5. Добавляет разделители между разделами 6. Приводит таблицы к единому виду Использование: python3 /opt/trueconf_bot/search_bot/optimize_documents.py <путь_к_каталогу> Пример: python3 /opt/trueconf_bot/search_bot/optimize_documents.py "/opt/documents_xk/ready_md/АОХКСибцем/07 Служба Вице-президента по экономике и финансам/ДИТ/02 Регламенты деятельности/" """ import os import re import sys import time import requests import base64 # Конфигурация FILEBROWSER_URL = "https://smb.dddennnisss.ru" FILEBROWSER_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJGaWxlQnJvd3NlciBRdWFudHVtIiwiZXhwIjoyMzAyNzM1NzA3LCJpYXQiOjE3ODQzMzU3MDcsImJlbG9uZ3NUbyI6MSwiUGVybWlzc2lvbnMiOnsiYXBpIjp0cnVlLCJhZG1pbiI6dHJ1ZSwibW9kaWZ5Ijp0cnVlLCJzaGFyZSI6dHJ1ZSwicmVhbHRpbWUiOmZhbHNlLCJkZWxldGUiOnRydWUsImNyZWF0ZSI6dHJ1ZSwiZG93bmxvYWQiOnRydWV9fQ.QBKlh3NQJeh4aeMiKLkhg0tF8hxk-Oh2KLsXLSbuvm8" SOURCE_NAME = "SSD-Storage" def remove_footers(content): """Удалить футеры страниц.""" # Удалить "АО «ХК «Сибцем»\nТип документа: ...\nНаименование документа: ..." content = re.sub( r'АО «ХК «Сибцем»\nТип документа:.*?\nНаименование документа:.*?\n\n', '', content, flags=re.DOTALL ) # Удалить "Стр. X из Y" content = re.sub(r'Стр\. \d+ из \d+\n\n', '', content) # Удалить "Дата утверждения: DD.MM.YYYY" content = re.sub(r'Дата утверждения: \d{2}\.\d{2}\.\d{4}\n\n', '', content) # Удалить "Ведущее подразделение: ..." content = re.sub(r'Ведущее подразделение:.*?\n\n', '', content) return content def fix_headings(content): """Выровнять иерархию заголовков: все на уровень ##.""" content = re.sub(r'^(#+)\s+(.+)$', r'## \2', content, flags=re.MULTILINE) return content def add_dividers(content): """Добавить разделители между основными разделами.""" # Разделитель перед Оглавлением content = re.sub( r'(\n)(## )(Оглавление)', r'\1\n---\n\1\2\3', content ) # Разделители перед разделами 1-9 content = re.sub( r'(\n)(## )(\s*(?:1\.|2\.|3\.|4\.|5\.|6\.|7\.|8\.|9\.))', r'\1\n---\n\1\2\3', content ) # Разделители перед Приложениями content = re.sub( r'(\n)(## )(Приложение)', r'\1\n---\n\1\2\3', content ) # Разделитель перед Листом согласований content = re.sub( r'(\n)(## )(Лист согласований)', r'\1\n---\n\1\2\3', content ) return content def fix_tables(content): """Привести все таблицы к единому виду с thead/tbody.""" def fix_table(table): if '' in table and '' in table: return table rows = re.findall(r'(.*?)', table, re.DOTALL) if not rows: return table header = '' + rows[0] + '' body = '' for row in rows[1:]: body += '' + row + '' body += '' return '' + header + body + '
' return re.sub(r'.*?
', lambda m: fix_table(m.group(0)), content, flags=re.DOTALL) def merge_terms_tables(content): """Объединить разбитые таблицы терминов.""" # Поиск таблиц терминов terms_pattern = r'(.*?Термины.*?
)' matches = re.findall(terms_pattern, content, re.DOTALL) if len(matches) > 1: # Объединяем все таблицы терминов в одну merged = '' for table in matches: rows = re.findall(r'(.*?)', table, re.DOTALL) for row in rows[1:]: # Пропускаем заголовок merged += row merged += '
ТерминОпределение
' content = content.replace(matches[0], merged) return content def fix_approval_block(content): """Форматировать блок УТВЕРЖДАЮ.""" # Паттерн 1: "УТВЕРЖДАЮ\nПрезидент\n\nО.В. Шарыкин\n\n«XX» месяц год г." approval_patterns = [ r'(УТВЕРЖДАУ\nПрезидент\n\nО\.В\. Шарыкин\n\n«\d+» \w+ \d{4} г\.)', r'(УТВЕРЖДАУ\nПрезидент\n\nО\.В\. Шарыкин\n\n«\d+» \w+ \d{4} г\.)', ] for pattern in approval_patterns: match = re.search(pattern, content) if match: old_text = match.group(0) new_text = f'''
УТВЕРЖДАУ
Президент
О.В. Шарыкин
{old_text.split("«")[1].split("г.")[0]} г.
''' content = content.replace(old_text, new_text) break return content def upload_to_filebrowser(content, filename): """Загрузить файл в filebrowser.""" # Добавить "_improved" перед расширением if filename.endswith('.md'): improved_filename = filename[:-3] + '_improved.md' else: improved_filename = filename + '_improved' session = requests.Session() session.cookies.set("filebrowser_quantum_jwt", FILEBROWSER_TOKEN, domain="smb.dddennnisss.ru") url = f"{FILEBROWSER_URL}/api/resources" params = {"path": improved_filename, "source": SOURCE_NAME} r = session.put(url, params=params, data=content) if r.status_code == 200: print(f"✓ Файл загружен: {improved_filename}") # Проверить r = session.get(f"{FILEBROWSER_URL}/api/resources", params={"path": "/", "source": SOURCE_NAME}) if r.status_code == 200: data = r.json() items = data.get("files", []) + data.get("folders", []) for item in items: if improved_filename in item["name"]: print(f"✓ Размер: {item['size']} байт") break else: print(f"✗ Ошибка загрузки: {r.status_code} - {r.text[:200]}") return improved_filename def optimize_document(md_path): """Основная функция оптимизации документа.""" start_time = time.time() print(f"\n📄 Обработка документа: {md_path.split('/')[-1]}") print("=" * 60) # Шаг 1: Читать MD файл print("\n📥 Шаг 1: Чтение MD...") try: with open(md_path, 'r', encoding='utf-8') as f: md_content = f.read() except Exception as e: print(f"✗ Ошибка при чтении: {e}") return print(f"✓ MD прочитан: {len(md_content)} символов") # Шаг 2: Применить паттерны print("\n🔧 Шаг 2: Применение паттернов...") # 2.1 Удалить футеры content = remove_footers(md_content) print(" ✓ Футеры удалены") # 2.2 Выровнять иерархию заголовков content = fix_headings(content) print(" ✓ Иерархия заголовков выровнена") # 2.3 Добавить разделители content = add_dividers(content) print(" ✓ Разделители добавлены") # 2.4 Привести таблицы к единому виду content = fix_tables(content) print(" ✓ Таблицы приведены к единому виду") # 2.5 Объединить таблицы терминов content = merge_terms_tables(content) print(" ✓ Таблицы терминов объединены") # 2.6 Форматировать блок УТВЕРЖДАЮ content = fix_approval_block(content) print(" ✓ Блок УТВЕРЖДАУ отформатирован") # Сохранить улучшенную версию improved_path = md_path.replace('.md', '_improved.md') with open(improved_path, "w", encoding="utf-8") as f: f.write(content) print(f"\n📊 Результаты:") print(f" Исходный размер: {len(md_content)} символов") print(f" Улучшенный размер: {len(content)} символов") # Показать структуру sections = re.findall(r'^(##)\s+(.+)$', content, re.MULTILINE) print(f" Разделов: {len(sections)}") tables = re.findall(r'', content) print(f" Таблиц: {len(tables)}") # Показать первые 300 символов print(f"\n📝 Начало файла:") print(content[:300].replace('\n', '\\n')) # Загрузить в filebrowser print("\n📤 Шаг 3: Загрузка в filebrowser...") filename = md_path.split('/')[-1] upload_to_filebrowser(content, filename) elapsed = time.time() - start_time print(f"\n{'=' * 60}") print(f"✅ Готово! Время выполнения: {elapsed:.1f} сек") print(f"{'=' * 60}") def process_directory(directory): """Обработать все MD файлы в каталоге.""" start_time = time.time() print(f"📂 Обработка каталога: {directory}") print("=" * 60) # Найти все MD файлы md_files = [] for root, dirs, files in os.walk(directory): for file in files: if file.endswith('.md'): md_files.append(os.path.join(root, file)) print(f"Найдено {len(md_files)} MD файлов") # Обработать каждый файл for md_path in md_files: try: optimize_document(md_path) except Exception as e: print(f"✗ Ошибка при обработке {md_path}: {e}") elapsed = time.time() - start_time print(f"\n{'=' * 60}") print(f"✅ Обработка каталога завершена! Общее время: {elapsed:.1f} сек") print(f"{'=' * 60}") if __name__ == "__main__": if len(sys.argv) < 2: print("Использование:") print(" python3 optimize_documents.py <путь_к_каталогу>") print("\nПример:") print(' python3 optimize_documents.py "/opt/documents_xk/ready_md/АОХКСибцем/07 Служба Вице-президента по экономике и финансам/ДИТ/02 Регламенты деятельности/"') sys.exit(1) directory = sys.argv[1] process_directory(directory)