notebookvb
This commit is contained in:
@@ -1,140 +1,166 @@
|
||||
"""
|
||||
01 - Přihlášení na portál VoZP (prehled-zprav-ve-schrankach)
|
||||
Otevře Chrome, přihlásí se certifikátem přes Signer komponentu a naviguje na schránku zpráv.
|
||||
Okno zůstane otevřené — skript čeká na stisk Enter.
|
||||
Použití: python 01_prihlaseni.py
|
||||
01 - Přihlášení na portál VoZP — extrakce cookies (jako admin).
|
||||
|
||||
POSTUP:
|
||||
1. Spusť: python 01_prihlaseni.py
|
||||
2. Vyskočí UAC — schval (skript potřebuje admin pro čtení Chrome cookies
|
||||
kvůli App-Bound Encryption v Chrome v130+).
|
||||
3. Otevře se nové okno s běžícím skriptem (admin).
|
||||
4. Skript otevře Chrome (jako user) na VoZP login.
|
||||
5. Přihlas se certifikátem (NMSigner vyskočí — klikni ANO).
|
||||
6. Vrať se k Chrome → ZAVŘI ho (všechna okna).
|
||||
7. Stiskni Enter v admin okně skriptu.
|
||||
8. Cookies se uloží do vozp_cookies.json.
|
||||
|
||||
POŽADAVKY:
|
||||
pip install rookiepy
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import winreg
|
||||
|
||||
LOGIN_URL = "https://portal.vozp.cz/app/prihlaseni"
|
||||
INBOX_URL = "https://portal.vozp.cz/app/prehled-zprav-ve-schrankach"
|
||||
CHROME_PROFILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "chrome_profile"))
|
||||
COOKIES_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), "vozp_cookies.json"))
|
||||
|
||||
|
||||
def load_cookies(context) -> int:
|
||||
"""Načte dříve uložené cookies zpět do kontextu."""
|
||||
if not os.path.exists(COOKIES_FILE):
|
||||
return 0
|
||||
def is_admin() -> bool:
|
||||
try:
|
||||
with open(COOKIES_FILE, "r", encoding="utf-8") as f:
|
||||
cookies = json.load(f)
|
||||
context.add_cookies(cookies)
|
||||
return len(cookies)
|
||||
except Exception as e:
|
||||
print(f" Chyba při načítání cookies: {e}")
|
||||
return 0
|
||||
return ctypes.windll.shell32.IsUserAnAdmin() != 0
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def save_cookies(context) -> int:
|
||||
"""Uloží VoZP cookies (i session-only) do JSON souboru."""
|
||||
def relaunch_as_admin() -> None:
|
||||
print("Skript potřebuje admin práva (Chrome v130+ App-Bound Encryption).")
|
||||
print("Otevírám UAC...")
|
||||
params = " ".join(f'"{a}"' for a in sys.argv)
|
||||
ret = ctypes.windll.shell32.ShellExecuteW(
|
||||
None, "runas", sys.executable, params, None, 1
|
||||
)
|
||||
if ret <= 32:
|
||||
print(f"UAC selhalo (kód {ret}). Spusť ručně jako admin.")
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def open_chrome_as_user(url: str) -> None:
|
||||
"""Spustí default browser jako standardní user, i když Python běží jako admin."""
|
||||
# explorer.exe běží jako user a otevře URL v defaultním prohlížeči
|
||||
try:
|
||||
all_cookies = context.cookies()
|
||||
vozp = [c for c in all_cookies if any(
|
||||
d in c.get("domain", "") for d in ["vozp.cz", "portalzp.cz"]
|
||||
)]
|
||||
with open(COOKIES_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(vozp, f, indent=2, ensure_ascii=False)
|
||||
return len(vozp)
|
||||
except Exception as e:
|
||||
print(f" Chyba při ukládání cookies: {e}")
|
||||
return 0
|
||||
|
||||
|
||||
def _delete_chrome_cert_policy() -> None:
|
||||
"""Smaže AutoSelectCertificateForUrls politiku — Chrome pak zobrazí dialog přirozeně."""
|
||||
key_path = r"SOFTWARE\Policies\Google\Chrome\AutoSelectCertificateForUrls"
|
||||
try:
|
||||
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, access=winreg.KEY_SET_VALUE)
|
||||
winreg.DeleteValue(key, "1")
|
||||
winreg.CloseKey(key)
|
||||
subprocess.Popen(["explorer.exe", url])
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
# Fallback
|
||||
import webbrowser
|
||||
webbrowser.open(url)
|
||||
|
||||
|
||||
def read_cookies_rookiepy() -> list[dict]:
|
||||
import rookiepy
|
||||
raw = rookiepy.chrome(["vozp.cz", ".vozp.cz", "portal.vozp.cz", "portalzp.cz"])
|
||||
out = []
|
||||
for c in raw:
|
||||
dom = c["domain"]
|
||||
if not any(d in dom for d in ["vozp.cz", "portalzp.cz"]):
|
||||
continue
|
||||
out.append({
|
||||
"name": c["name"],
|
||||
"value": c["value"],
|
||||
"domain": dom if dom.startswith(".") else "." + dom,
|
||||
"path": c.get("path") or "/",
|
||||
"expires": int(c["expires"]) if c.get("expires") else -1,
|
||||
"secure": bool(c.get("secure", False)),
|
||||
"httpOnly": bool(c.get("http_only", False)),
|
||||
"sameSite": "Lax",
|
||||
})
|
||||
return out
|
||||
|
||||
|
||||
def read_cookies_browser_cookie3() -> list[dict]:
|
||||
import browser_cookie3
|
||||
cj = browser_cookie3.chrome(domain_name="vozp.cz")
|
||||
out = []
|
||||
for c in cj:
|
||||
if not any(d in c.domain for d in ["vozp.cz", "portalzp.cz"]):
|
||||
continue
|
||||
out.append({
|
||||
"name": c.name,
|
||||
"value": c.value,
|
||||
"domain": c.domain if c.domain.startswith(".") else "." + c.domain,
|
||||
"path": c.path or "/",
|
||||
"expires": int(c.expires) if c.expires else -1,
|
||||
"secure": bool(c.secure),
|
||||
"httpOnly": False,
|
||||
"sameSite": "Lax",
|
||||
})
|
||||
return out
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if not is_admin():
|
||||
relaunch_as_admin()
|
||||
return # nedosažitelné
|
||||
|
||||
print("=" * 60)
|
||||
print("BĚŽÍM JAKO ADMIN — PŘIHLÁŠENÍ DO VoZP")
|
||||
print("=" * 60)
|
||||
print(f"1. Otevírám Chrome (jako user) na: {LOGIN_URL}")
|
||||
print("2. Přihlas se certifikátem (NMSigner → klikni ANO)")
|
||||
print("3. Po přihlášení ZAVŘI Chrome úplně (všechna okna)")
|
||||
print("4. Vrať se sem a stiskni Enter")
|
||||
print("=" * 60)
|
||||
|
||||
open_chrome_as_user(LOGIN_URL)
|
||||
|
||||
input("\nAž jsi přihlášen/a a Chrome ZAVŘENÝ, stiskni Enter...")
|
||||
|
||||
cookies: list[dict] = []
|
||||
last_err = ""
|
||||
|
||||
print("\nČtu cookies (jako admin)...")
|
||||
try:
|
||||
from playwright.sync_api import sync_playwright
|
||||
cookies = read_cookies_rookiepy()
|
||||
print(f" rookiepy OK: {len(cookies)} cookies")
|
||||
except ImportError:
|
||||
print("Chybí playwright: pip install playwright && playwright install chrome")
|
||||
last_err = "rookiepy není nainstalovaný"
|
||||
print(f" {last_err} — zkouším browser_cookie3...")
|
||||
except Exception as e:
|
||||
last_err = f"rookiepy: {e}"
|
||||
print(f" rookiepy selhalo: {e} — zkouším browser_cookie3...")
|
||||
|
||||
if not cookies:
|
||||
try:
|
||||
cookies = read_cookies_browser_cookie3()
|
||||
print(f" browser_cookie3 OK: {len(cookies)} cookies")
|
||||
except ImportError:
|
||||
print(" browser_cookie3 není nainstalovaný.")
|
||||
except Exception as e:
|
||||
print(f" browser_cookie3: {e}")
|
||||
|
||||
if not cookies:
|
||||
print("\nCookies se nepodařilo přečíst ani jako admin.")
|
||||
print("Zkontroluj, že:")
|
||||
print(" - Chrome je úplně zavřený (Task Manager → žádný chrome.exe)")
|
||||
print(" - Jsi se na VoZP přihlásil/a (DB má nové záznamy)")
|
||||
print(" - Máš nainstalované: pip install rookiepy browser-cookie3")
|
||||
input("\nEnter pro zavření...")
|
||||
sys.exit(1)
|
||||
|
||||
_delete_chrome_cert_policy()
|
||||
with open(COOKIES_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(cookies, f, indent=2, ensure_ascii=False)
|
||||
|
||||
with sync_playwright() as p:
|
||||
context = p.chromium.launch_persistent_context(
|
||||
user_data_dir=CHROME_PROFILE,
|
||||
channel="chrome",
|
||||
headless=False,
|
||||
slow_mo=200,
|
||||
ignore_https_errors=True,
|
||||
args=["--force-renderer-accessibility"],
|
||||
)
|
||||
try:
|
||||
loaded = load_cookies(context)
|
||||
print(f"Profil: {CHROME_PROFILE}")
|
||||
print(f"Cookies z JSON: {loaded}")
|
||||
print(f"\nUloženo {len(cookies)} cookies do {COOKIES_FILE}")
|
||||
for c in cookies:
|
||||
exp = c["expires"]
|
||||
tag = "PERSISTENT" if exp > 0 else "SESSION"
|
||||
print(f" - {c['name'][:50]} ({c['domain']}) [{tag}]")
|
||||
|
||||
page = context.new_page()
|
||||
|
||||
# Zkus rovnou inbox — pokud jsme přihlášeni, budeme tam
|
||||
print("Naviguji na schránku zpráv...")
|
||||
try:
|
||||
page.goto(INBOX_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception as e:
|
||||
print(f"Navigace: {e}")
|
||||
|
||||
# Pokud nás přesměrovalo na login stránku
|
||||
if "prihlaseni" in page.url or "login" in page.url.lower():
|
||||
print("Přihlašovací stránka — klikám na 'Přihlásit se certifikátem'...")
|
||||
try:
|
||||
page.goto(LOGIN_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception as e:
|
||||
print(f"Navigace na login: {e}")
|
||||
|
||||
cert_btn = page.locator("button").filter(has_text="certifikátem").first
|
||||
cert_btn.wait_for(state="visible", timeout=10_000)
|
||||
cert_btn.click(no_wait_after=True)
|
||||
|
||||
print("Vyskočí Signer komponenta — klikněte ANO (max 60 s)...")
|
||||
time.sleep(30)
|
||||
|
||||
# Po Signeru naviguj na inbox
|
||||
print("Naviguji na schránku zpráv...")
|
||||
try:
|
||||
page.goto(INBOX_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception as e:
|
||||
print(f"Navigace po auth: {e}")
|
||||
|
||||
if "prehled-zprav" not in page.url and "uvodni-stranka" not in page.url:
|
||||
print(f"Přihlášení selhalo. URL: {page.url}")
|
||||
return
|
||||
|
||||
print(f"OK — přihlášení úspěšné. URL: {page.url}")
|
||||
|
||||
# Diagnostika cookies
|
||||
after = context.cookies()
|
||||
vozp_cookies = [c for c in after if any(
|
||||
d in c.get("domain", "") for d in ["vozp.cz", "portalzp.cz"]
|
||||
)]
|
||||
print(f"Cookies po auth: {len(vozp_cookies)}")
|
||||
for c in vozp_cookies:
|
||||
exp = c.get("expires", -1)
|
||||
persistent = "PERSISTENT" if exp > 0 else "SESSION-ONLY"
|
||||
print(f" - {c['name'][:60]} ({c['domain']}) [{persistent}]")
|
||||
|
||||
print("Okno zůstane otevřené. Stiskněte Enter pro zavření...")
|
||||
input()
|
||||
|
||||
finally:
|
||||
saved = save_cookies(context)
|
||||
print(f"Uloženo {saved} VoZP cookies do {COOKIES_FILE}")
|
||||
context.close()
|
||||
input("\nHotovo. Enter pro zavření...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -232,32 +232,20 @@ def process_schránka(page, session: req.Session, segment: str, name: str, alrea
|
||||
|
||||
|
||||
def ensure_logged_in(page, context) -> bool:
|
||||
"""Ověří přihlášení. Pokud ne, provede přihlášení certifikátem."""
|
||||
"""Ověří přihlášení. Pokud cookies nestačí, upozorní na spuštění 01."""
|
||||
try:
|
||||
page.goto(INBOX_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception as e:
|
||||
print(f"Navigace: {e}")
|
||||
|
||||
if "prihlaseni" in page.url or "login" in page.url.lower():
|
||||
print("Nutné přihlášení — klikám na 'Přihlásit se certifikátem'...")
|
||||
try:
|
||||
page.goto(LOGIN_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception:
|
||||
pass
|
||||
cert_btn = page.locator("button").filter(has_text="certifikátem").first
|
||||
cert_btn.wait_for(state="visible", timeout=10_000)
|
||||
cert_btn.click(no_wait_after=True)
|
||||
print("Vyskočí Signer komponenta — klikněte ANO (max 60 s)...")
|
||||
time.sleep(40)
|
||||
try:
|
||||
page.goto(INBOX_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception:
|
||||
pass
|
||||
if "prihlaseni" in page.url:
|
||||
print("Přihlášení selhalo.")
|
||||
print("=" * 60)
|
||||
print("Cookies neplatné nebo vypršely.")
|
||||
print("Spusť znovu: python 01_prihlaseni.py")
|
||||
print("=" * 60)
|
||||
return False
|
||||
|
||||
print(f"Přihlášení OK. URL: {page.url}")
|
||||
print(f"Přihlášení OK (přes cookies). URL: {page.url}")
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -235,25 +235,13 @@ def ensure_logged_in(page, context) -> bool:
|
||||
print(f"Navigace: {e}")
|
||||
|
||||
if "prihlaseni" in page.url or "login" in page.url.lower():
|
||||
print("Nutné přihlášení — klikám na 'Přihlásit se certifikátem'...")
|
||||
try:
|
||||
page.goto(LOGIN_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception:
|
||||
pass
|
||||
cert_btn = page.locator("button").filter(has_text="certifikátem").first
|
||||
cert_btn.wait_for(state="visible", timeout=10_000)
|
||||
cert_btn.click(no_wait_after=True)
|
||||
print("Vyskočí Signer komponenta — klikněte ANO (max 60 s)...")
|
||||
time.sleep(40)
|
||||
try:
|
||||
page.goto(INBOX_URL, wait_until="domcontentloaded", timeout=30_000)
|
||||
except Exception:
|
||||
pass
|
||||
if "prihlaseni" in page.url:
|
||||
print("Přihlášení selhalo.")
|
||||
print("=" * 60)
|
||||
print("Cookies neplatné nebo vypršely.")
|
||||
print("Spusť znovu: python 01_prihlaseni.py")
|
||||
print("=" * 60)
|
||||
return False
|
||||
|
||||
print(f"Přihlášení OK. URL: {page.url}")
|
||||
print(f"Přihlášení OK (přes cookies). URL: {page.url}")
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
@echo off
|
||||
REM Spustí Chrome s otevřeným CDP portem 9222 pro extrakci cookies.
|
||||
REM Před spuštěním ukončí všechny běžící Chrome procesy
|
||||
REM (Chrome neumožňuje dvě instance nad stejným profilem).
|
||||
|
||||
echo Ukoncuji bezici Chrome procesy...
|
||||
taskkill /f /im chrome.exe >nul 2>&1
|
||||
timeout /t 2 /nobreak >nul
|
||||
|
||||
set "CHROME_EXE=C:\Program Files\Google\Chrome\Application\chrome.exe"
|
||||
if not exist "%CHROME_EXE%" set "CHROME_EXE=C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
|
||||
if not exist "%CHROME_EXE%" set "CHROME_EXE=%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe"
|
||||
|
||||
echo Spoustim Chrome s debug portem 9222...
|
||||
start "" "%CHROME_EXE%" ^
|
||||
--remote-debugging-port=9222 ^
|
||||
--remote-allow-origins=* ^
|
||||
--user-data-dir="%LOCALAPPDATA%\Google\Chrome\User Data" ^
|
||||
--profile-directory="Default" ^
|
||||
--restore-last-session=false ^
|
||||
--hide-crash-restore-bubble ^
|
||||
--no-first-run ^
|
||||
--no-default-browser-check ^
|
||||
https://portal.vozp.cz/app/prihlaseni
|
||||
|
||||
echo.
|
||||
echo Chrome se spousti. Po prihlaseni do VoZP spust:
|
||||
echo python 01_prihlaseni.py
|
||||
echo.
|
||||
pause
|
||||
Reference in New Issue
Block a user