import os import subprocess import time import re from pathlib import Path from playwright.sync_api import sync_playwright # --- CONFIG --- STORAGE_ROOT = Path("/app/services/gis_harvester/contracts") NAS_IP = "192.168.10.105" NAS_PATH = "/volume1/web/legal/gis/contracts" BOT_TOKEN = "8725618164:AAH1tGalq-pw1l0t4P5c0sdLkCVJdh7IE7M" CHAT_ID = "197957361" def send_tg_status(msg): subprocess.run(["curl", "-s", "-X", "POST", f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage", "-d", f"chat_id={CHAT_ID}&text={msg}&parse_mode=markdown"]) def sync_to_nas(local_path, remote_folder): target = f"{NAS_PATH}/{remote_folder}" subprocess.run(["ssh", f"matrixhasyou@{NAS_IP}", f"mkdir -p '{target}'"]) for f in os.listdir(local_path): src = local_path / f dst = f"{target}/{f}" with open(src, "rb") as fd: subprocess.run(["ssh", f"matrixhasyou@{NAS_IP}", f"cat > '{dst}'"], stdin=fd) def run_harvest(): with sync_playwright() as p: try: browser = p.chromium.connect_over_cdp("http://127.0.0.1:9222") page = browser.contexts[0].pages[0] print("[*] Анализ списка договоров на экране...") # Находим все ссылки, содержащие слово 'Договор' links = page.locator("a:has-text('Договор')").all() total = len(links) if total == 0: send_tg_status("❌ ОШИБКА: Договоры на экране не обнаружены. Проверьте VNC.") return send_tg_status(f"📜 **ЖНЕЦ ДОГОВОРОВ v2.0**\nОбнаружено в списке: {total} договоров.") for i in range(total): # Переполучаем список т.к. DOM меняется current_links = page.locator("a:has-text('Договор')").all() link = current_links[i] name_text = link.inner_text().strip()[:100].replace('/', '_').replace(' ', '_') print(f"[{i+1}/{total}] Вскрываем: {name_text}...") # Клик link.click() page.wait_for_load_state("networkidle") time.sleep(15) # Папка для дела case_dir = STORAGE_ROOT / name_text case_dir.mkdir(parents=True, exist_ok=True) # 1. СКРИНШОТ (Улика) page.screenshot(path=str(case_dir / "contract_evidence.png"), full_page=True) # 2. СКАЧИВАНИЕ try: # Ищем кнопку 'Скачать все' или ссылки на файлы # В договорах часто есть вкладка 'Информация о договоре' или 'Файлы' download_btn = page.get_by_text("Скачать все").first if not download_btn.is_visible(): # Попробуем найти любые ссылки на скачивание download_btn = page.locator("a[title*='Скачать'], button:has-text('Скачать')").first if download_btn.is_visible(): with page.expect_download(timeout=120000) as download_info: download_btn.click() download = download_info.value zip_path = case_dir / "contract_archive.zip" download.save_as(str(zip_path)) status = "✅ ZIP + Скрин" else: status = "⚠️ Только скрин (кнопка скачивания не найдена)" except Exception as e: status = f"❌ Ошибка скачивания: {str(e)[:50]}" # СИНХРОНИЗАЦИЯ sync_to_nas(case_dir, name_text) # ОТЧЕТ bar = "█" * ((i+1)*10//total) + "░" * (10 - ((i+1)*10//total)) send_tg_status(f"📜 **{name_text}**\nСтатус: {status}\n\n[{bar}] {i+1}/{total}") # НАЗАД page.go_back() time.sleep(10) send_tg_status("🏁 Жатва договоров УСПЕШНО ЗАВЕРШЕНА.") browser.close() except Exception as e: send_tg_status(f"🚨 КАТАСТРОФА ЖНЕЦА ДОГОВОРОВ: {str(e)}") if __name__ == "__main__": os.makedirs(STORAGE_ROOT, exist_ok=True) run_harvest()