z230
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
# =============================================================================
|
||||
# Název: sipiq_download_v2.1.py
|
||||
# Verze: 2.1
|
||||
# Datum: 2026-06-19
|
||||
# Autor: Claude Code (pro MUDr. Vladimíra Buzalku)
|
||||
# Popis: Automatické stažení SIPIQ survey reportu (CSV) z Qualtrics přes
|
||||
# Playwright. Přihlásí se (username/password), otevře Data & Analysis
|
||||
# studie 77242113UCO3002 (SV_9AdeNaNyohp5fNQ), spustí Export & Import →
|
||||
# Export Data → CSV → Download a stažený soubor uloží s timestampem do
|
||||
# U:\Dropbox\!!!Days\Downloads Z230\.
|
||||
#
|
||||
# v2.1: přepínač --import → po úspěšném stažení rovnou spustí
|
||||
# sipiq_import_v1.3.py --csv "<stažený soubor>" (delta import do Mongo,
|
||||
# NEpřesouvá soubor). --scope se předá importu (default czsk).
|
||||
#
|
||||
# Proč Playwright a ne API: účet NEMÁ povolené API na úrovni účtu;
|
||||
# interní export běží jen na session cookies + interní fileUrl
|
||||
# (riptooth.service.consul) nedostupné zvenčí. Playwright se přihlásí
|
||||
# sám (řeší expiraci session) a stažení nechá na prohlížeči.
|
||||
#
|
||||
# Credentials: ROOT .env (QUALTRICS_USER / QUALTRICS_PASS), fallback
|
||||
# na zabudované hodnoty účtu sipiq.
|
||||
# Verze 1.0 (requests/API) a 2.0 (bez --import) přesunuty do TRASH.
|
||||
# =============================================================================
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from playwright.sync_api import sync_playwright, TimeoutError as PWTimeout
|
||||
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
load_dotenv(os.path.join(_ROOT, ".env"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
DC = "janssenfeasibility.co1"
|
||||
SURVEY = "SV_9AdeNaNyohp5fNQ"
|
||||
USER = os.environ.get("QUALTRICS_USER", "77242113uco3002_sipiq")
|
||||
PWD = os.environ.get("QUALTRICS_PASS", "77242113uco3002_sipiq")
|
||||
LOGIN_URL = "https://login.qualtrics.com/login"
|
||||
RESP_URL = f"https://{DC}.qualtrics.com/responses/#/surveys/{SURVEY}"
|
||||
|
||||
OUT_DIR = r"U:\Dropbox\!!!Days\Downloads Z230"
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
PROFILE = os.path.join(HERE, "qualtrics_profile")
|
||||
IMPORT_SCRIPT = os.path.join(HERE, "sipiq_import_v1.3.py")
|
||||
DEBUG_DIR = HERE
|
||||
|
||||
|
||||
def dbg(page, name):
|
||||
try:
|
||||
page.screenshot(path=os.path.join(DEBUG_DIR, f"_dl_{name}.png"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def ensure_login(page):
|
||||
page.goto(LOGIN_URL, timeout=120000)
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
page.wait_for_timeout(3000)
|
||||
field = page.locator("#UserName, input[name='username'], #username").first
|
||||
if field.is_visible(timeout=5000):
|
||||
print("Přihlašuji se…")
|
||||
field.fill(USER)
|
||||
page.locator("#UserPassword, input[name='password'], #password").first.fill(PWD)
|
||||
page.locator("#loginButton, button[type='submit'], #login-button").first.click()
|
||||
page.wait_for_timeout(8000)
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
else:
|
||||
print("Session aktivní, přihlášení přeskočeno.")
|
||||
|
||||
|
||||
def open_data_table(page):
|
||||
page.goto(RESP_URL, timeout=120000)
|
||||
page.wait_for_load_state("domcontentloaded")
|
||||
page.get_by_role("button", name="Export & Import").wait_for(timeout=120000)
|
||||
page.wait_for_timeout(2000)
|
||||
print("Data & Analysis načteno.")
|
||||
|
||||
|
||||
def do_export(page):
|
||||
page.get_by_role("button", name="Export & Import").click()
|
||||
page.wait_for_timeout(1500)
|
||||
dbg(page, "01_menu")
|
||||
page.get_by_text("Export Data", exact=False).first.click()
|
||||
page.wait_for_timeout(3000)
|
||||
dbg(page, "02_modal")
|
||||
try:
|
||||
page.get_by_role("tab", name="CSV").click(timeout=5000)
|
||||
except PWTimeout:
|
||||
try:
|
||||
page.get_by_text("CSV", exact=True).first.click(timeout=5000)
|
||||
except Exception:
|
||||
print("CSV tab nenalezen, spoléhám na default.")
|
||||
page.wait_for_timeout(1500)
|
||||
dbg(page, "03_csv")
|
||||
print("Spouštím Download…")
|
||||
with page.expect_download(timeout=180000) as dl_info:
|
||||
page.get_by_role("button", name="Download").last.click()
|
||||
return dl_info.value
|
||||
|
||||
|
||||
def download(headless):
|
||||
os.makedirs(OUT_DIR, exist_ok=True)
|
||||
with sync_playwright() as pw:
|
||||
ctx = pw.chromium.launch_persistent_context(
|
||||
PROFILE, headless=headless, accept_downloads=True,
|
||||
args=["--start-maximized"], no_viewport=not headless)
|
||||
page = ctx.pages[0] if ctx.pages else ctx.new_page()
|
||||
try:
|
||||
ensure_login(page)
|
||||
open_data_table(page)
|
||||
dl = do_export(page)
|
||||
stamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
suggested = dl.suggested_filename or "sipiq_export.csv"
|
||||
target = os.path.join(OUT_DIR, f"{stamp} {suggested}")
|
||||
dl.save_as(target)
|
||||
print("Staženo:", target)
|
||||
return target
|
||||
except Exception as e:
|
||||
dbg(page, "99_error")
|
||||
print("CHYBA při stahování:", repr(e), file=sys.stderr)
|
||||
raise
|
||||
finally:
|
||||
page.wait_for_timeout(1500)
|
||||
ctx.close()
|
||||
|
||||
|
||||
def run_import(csv_path, scope, dry_run):
|
||||
cmd = [sys.executable, IMPORT_SCRIPT, "--csv", csv_path, "--scope", scope]
|
||||
if dry_run:
|
||||
cmd.append("--dry-run")
|
||||
print("\n=== IMPORT do Mongo ===")
|
||||
print("Spouštím:", " ".join(f'"{c}"' if " " in c else c for c in cmd))
|
||||
rc = subprocess.call(cmd)
|
||||
if rc != 0:
|
||||
print(f"CHYBA: import skončil s kódem {rc}.", file=sys.stderr)
|
||||
return rc
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Stažení SIPIQ CSV z Qualtrics (+ volitelný import)")
|
||||
ap.add_argument("--headless", action="store_true", help="bez okna (pro scheduler)")
|
||||
ap.add_argument("--import", dest="do_import", action="store_true",
|
||||
help="po stažení rovnou naimportovat do Mongo (sipiq_import_v1.3 --csv)")
|
||||
ap.add_argument("--scope", choices=["czsk", "all"], default="czsk",
|
||||
help="scope pro import (default czsk)")
|
||||
ap.add_argument("--dry-run", action="store_true",
|
||||
help="import jen jako náhled (předá se sipiq_import --dry-run)")
|
||||
args = ap.parse_args()
|
||||
|
||||
csv_path = download(args.headless)
|
||||
|
||||
if args.do_import:
|
||||
rc = run_import(csv_path, args.scope, args.dry_run)
|
||||
sys.exit(rc)
|
||||
else:
|
||||
print("\nHOTOVO. (Import nespuštěn — přidej --import pro napojení na Mongo.)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user