#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Логин в hh.ru → сохраняет сессию в session/storage.json. Открывает НАСТОЯЩИЙ браузер (не headless). Войдите в свой аккаунт hh любым способом (почта/пароль, код из смс/письма, госуслуги — как обычно). Скрипт сам поймает момент входа по cookie `hhrole=applicant` и сохранит сессию. После этого можно закрывать. На сервере без экрана — запустите login.py на своём компьютере, затем скопируйте файл session/storage.json на сервер (см. README). """ import asyncio, json, sys from pathlib import Path from playwright.async_api import async_playwright BASE = Path(__file__).resolve().parent SESSION = BASE / "session" / "storage.json" SESSION.parent.mkdir(parents=True, exist_ok=True) async def main(): print("Открываю браузер… войдите в hh.ru в открывшемся окне.") print("Как только вход выполнен — жду до 5 минут и сохраняю сессию автоматически.") async with async_playwright() as p: b = await p.chromium.launch(headless=False) ctx = await b.new_context(locale="ru-RU", timezone_id="Europe/Moscow") pg = await ctx.new_page() await pg.goto("https://hh.ru/account/login", wait_until="domcontentloaded", timeout=60000) ok = False for _ in range(150): # 150 * 2s = 5 минут await pg.wait_for_timeout(2000) try: role = {c["name"]: c["value"] for c in await ctx.cookies("https://hh.ru")}.get("hhrole") except Exception: role = None if role == "applicant": ok = True break if ok: await ctx.storage_state(path=str(SESSION)) print(f"\n✅ Готово. Сессия сохранена: {SESSION}") print(" Теперь можно ставить на расписание (см. README.md).") else: print("\n❌ Не увидел вход (cookie hhrole=applicant) за 5 минут. Запустите ещё раз.") await b.close() sys.exit(0 if ok else 1) if __name__ == "__main__": asyncio.run(main())