96 lines
4.4 KiB
Python
96 lines
4.4 KiB
Python
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_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", "matrixhasyou@192.168.10.105", 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", "matrixhasyou@192.168.10.105", 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]
|
||
|
||
# Мы уже на нужной странице (#!/agreements/citizen/...)
|
||
print("[*] Сбор списка договоров...")
|
||
page.wait_for_load_state("networkidle")
|
||
time.sleep(10)
|
||
|
||
# Находим все ссылки на просмотр договоров
|
||
# Обычно это ссылки вида #!/agreements/view/...
|
||
links = page.locator("a[href*='agreements/view/']").all()
|
||
total = len(links)
|
||
send_tg_status(f"📜 **ЖНЕТЦ ДОГОВОРОВ**\nНайдено в разделе: {total} договоров.")
|
||
|
||
for i in range(total):
|
||
# Находим ссылки заново т.к. DOM может обновиться
|
||
current_links = page.locator("a[href*='agreements/view/']").all()
|
||
link = current_links[i]
|
||
|
||
# Получаем название договора из родительской строки
|
||
row = page.locator(f"tr:has(a[href*='{link.get_attribute('href')}'])")
|
||
name_text = row.inner_text().split('\n')[0][: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)
|
||
page.screenshot(path=str(case_dir / "contract_evidence.png"), full_page=True)
|
||
|
||
# СКАЧИВАНИЕ
|
||
try:
|
||
# В договорах кнопка может называться по-другому, но часто это тоже 'Скачать все'
|
||
download_btn = page.get_by_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_files.zip"
|
||
download.save_as(str(zip_path))
|
||
|
||
# Синхронизация
|
||
sync_to_nas(case_dir, name_text)
|
||
status = "✅ ZIP + Скрин"
|
||
else:
|
||
sync_to_nas(case_dir, name_text)
|
||
status = "⚠️ Только скрин (кнопка скачивания не найдена)"
|
||
except Exception as e:
|
||
status = f"❌ Ошибка: {str(e)}"
|
||
|
||
send_tg_status(f"📜 **ДОГОВОР: {name_text}**\nСтатус: {status}\n[{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()
|