""" 01 — Stáhni číselníky VZP z point.vzp.cz/Cms/Document (sekce „Číselníky"). Soubory přejmenuje do formátu: YYYY-MM-DD NázevLinku (popis).zip Ověří co již existuje v cílovém adresáři a stáhne pouze chybějící soubory. Použití: python 01_stahni_ciselniky.py [--dry-run] """ import json import os import re import sys # Windows konzole - povol UTF-8 výstup if sys.stdout.encoding != "utf-8": import io sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "Knihovny")) from najdi_dropbox import get_dropbox_root TARGET_DIR = os.path.join( get_dropbox_root(), "Ordinace", "Dokumentace_ke_zpracování", "Zúčtovací zprávy", "Číselníky" ) DRY_RUN = False # True = pouze zobraz co by se stáhlo, nic nestahuj CHROME_PROFILE = os.path.join(os.path.dirname(__file__), "chrome_profile") COOKIES_FILE = os.path.join(os.path.dirname(__file__), "vzp_cookies.json") # Issuer CN certifikátu v Windows store (CurrentUser\My) CERT_ISSUER_CN = "I.CA Public CA/RSA 06/2022" def _set_chrome_cert_policy() -> None: """Nastaví Chrome politiku AutoSelectCertificateForUrls — Chrome vybere certifikát automaticky.""" import winreg policy = json.dumps({ "pattern": "https://[*.]vzp.cz", "filter": {"ISSUER": {"CN": CERT_ISSUER_CN}}, }) key_path = r"SOFTWARE\Policies\Google\Chrome\AutoSelectCertificateForUrls" try: key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_path) winreg.SetValueEx(key, "1", 0, winreg.REG_SZ, policy) winreg.CloseKey(key) print(f" Chrome politika nastavena (issuer: {CERT_ISSUER_CN})") except Exception as e: print(f" Varování: nelze nastavit Chrome politiku: {e}") def load_cookies(context) -> int: if not os.path.exists(COOKIES_FILE): return 0 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 def save_cookies(context) -> int: try: vzp = [c for c in context.cookies() if "vzp.cz" in c.get("domain", "")] with open(COOKIES_FILE, "w", encoding="utf-8") as f: json.dump(vzp, f, indent=2, ensure_ascii=False) return len(vzp) except Exception as e: print(f" Chyba při ukládání cookies: {e}") return 0 def sanitize_filename(name: str) -> str: """Odstraní znaky nepovolené ve Windows názvech souborů.""" return re.sub(r'[\\/:*?"<>|]', '_', name).strip() # True = přidat popis v závorce do názvu souboru SECTIONS = { "Číselníky": True, "Soubor platných IČP": False, } def extract_entries(page) -> list[dict]: """ Projde tabulky sekcí definovaných v SECTIONS a vrátí seznam slovníků: orig_fname — původní název souboru z atributu download new_fname — nový název: YYYY-MM-DD Název [(popis)].zip link — Playwright Locator pro kliknutí """ entries = [] for section, include_description in SECTIONS.items(): rows = page.locator(f"h3:has-text('{section}') + table tbody tr").all() entries.extend(_extract_rows(rows, include_description=include_description)) return entries def _extract_rows(rows: list, include_description: bool = True) -> list[dict]: entries = [] i = 0 while i < len(rows): row = rows[i] dl_links = row.locator("a[download]").all() if not dl_links: i += 1 continue # Datum platnosti z