9.1 KiB
download_test_results_v1.1.py — dokumentace
Verze: 1.1 · Datum: 2026-05-29
Umístění: U:\PythonProject\Janssen\Covance_UCO3001\download_test_results_v1.1.py
Změny v1.1 oproti 1.0: přidána druhá studie 35472 (MDD) a druhý typ reportu Microbiology. Dříve jen 36940 + Standard.
1. Účel
Automatické stažení reportů Test Results z portálu Labcorp Sponsor Portal
(xsp.labcorp.com). Skript projde 2 studie × jejich centra × 2 typy reportu,
u každého vyexportuje grid do CSV a uloží ho timestampovaný do Source/.
| Studie | Interní ID | Význam | Počet center |
|---|---|---|---|
| UC | 36940 |
77242113UCO3001 | 12 |
| MDD | 35472 |
druhá studie | 5 |
Typy reportu (záložka v URL): Standard (/standard-test-results) a
Microbiology (/microbiology).
Celkem: (12 + 5) × 2 = 34 reportů (prázdná centra se přeskakují, viz 6.5).
2. Spuštění
U:\PythonProject\Janssen\.venv\Scripts\python.exe ^
U:\PythonProject\Janssen\Covance_UCO3001\download_test_results_v1.1.py
- Prohlížeč běží viditelně (
headless=False), maximalizovaný. - Persistent profile (
browser_profile/vedle skriptu) — session přežívá.
Dočasný test (1 centrum / studie)
Pro rychlé ověření stačí dočasně zúžit STUDIES, např.:
STUDIES = [
{"study": "36940", "sites": ["930557"]}, # UC — centrum s daty
{"study": "35472", "sites": ["898745"]}, # MDD — první centrum
]
→ proběhnou 4 reporty (2 centra × 2 typy). Po testu vrátit plný seznam.
3. Konfigurace (konstanty v hlavičce skriptu)
| Konstanta | Hodnota / význam |
|---|---|
EMAIL |
vbuzalka@its.jnj.com (login přes iMedidata/OKTA na xsp.covance.com) |
PASSWORD |
heslo k účtu (uložené přímo v kódu) |
LOGIN_URL |
https://xsp.covance.com/ — po přihlášení redirect na xsp.labcorp.com |
OUT_DIR |
U:\PythonProject\Janssen\Covance_UCO3001\Source |
PROFILE_DIR |
browser_profile/ vedle skriptu (persistent Chromium profil) |
STUDIES |
seznam studií, každá má study (interní ID) + sites (interní ID center) |
REPORT_TYPES |
standard-test-results/standard a microbiology/microbiology |
Interní čísla center
36940 (UC): 930551, 930556, 930525, 930549, 930543, 930547,
930555, 930557, 930539, 930536, 930553, 930531
35472 (MDD): 898745, 898739, 898733, 898744, 898727
Pozor: jsou to interní ID Labcorpu, nikoli čísla center typu CZ10001. V URL test-results se používá právě toto interní ID:
…/test-results/{SITE_ID}/{standard-test-results|microbiology}. (Pozn.: 36940 zdroj =download_equeries_report_v1.1.py SITES; 35472 zdroj = ručně dodaná čísla center.)
Generování REPORTS (DRY)
REPORTS se sestaví automaticky jako kartézský součin
STUDIES × sites × REPORT_TYPES. Přidání/odebrání centra, studie nebo typu
reportu = úprava příslušného seznamu, vzor URL i názvu se píše jen jednou.
4. Výstupní soubory
Formát názvu (timestamp + popisný název):
{YYYY-MM-DD_HHMMSS} sponsor-study-{STUDY}-test-results-{SITE_ID}-{TYP}.csv
{TYP} = standard nebo microbiology. Příklady:
2026-05-29_131121 sponsor-study-36940-test-results-930557-standard.csv
2026-05-29_131500 sponsor-study-36940-test-results-930557-microbiology.csv
2026-05-29_131800 sponsor-study-35472-test-results-898745-standard.csv
- Timestamp se generuje pro každý report zvlášť (v okamžiku exportu).
- Staré soubory se nikdy nemažou (verzování přes timestamp).
expect_downloadzachytí download event,save_as()uloží pod naším názvem.
5. Průběh skriptu (kroky + logging)
Každý krok se loguje s časem ([HH:MM:SS], flush=True).
| Fáze | Co dělá |
|---|---|
| START | spustí prohlížeč |
| LOGIN | otevře login; pokud je session aktivní, přihlášení přeskočí |
| Pro každý report (studie × centrum × typ): | |
| KROK 1/5 | navigace na report URL |
| KROK 2/5 | čeká na řádky gridu .ag-row nebo prázdný grid („No Data"); pak stabilizace počtu |
| KROK 3/5 | klik na viditelné tři tečky (more_horiz) → otevře menu |
| KROK 4/5 | klik na viditelné „Export to CSV" → zachytí download |
| KROK 5/5 | uloží soubor do OUT_DIR |
| KONEC | souhrn hotovo X/34 + seznam selhaných (site/typ) |
Log u každého reportu ukazuje i typ: === Centrum 930557 / microbiology (studie 36940) ===.
6. Klíčové technické poznatky (PROČ to tak je) — ověřeno přes Chrome MCP
Stránka test-results je Angular SPA s knihovnou MDL a tabulkou AG Grid. Microbiology záložka má stejnou strukturu jako Standard → vše níže platí pro oba.
6.1 Čekání na data = řádky AG Gridu
- Data jsou načtena, jakmile se objeví řádky
div.ag-row(count 0 → N). - Řádky jsou
position-absolute(virtuální render) → Playwright je nepovažuje za „visible". Proto:- ❌
wait_for_selector("div.ag-row")(default visible) timeoutuje. - ✅
wait_for_function("() => document.querySelectorAll('div.ag-row').length > 0").
- ❌
- Stabilizace: počet řádků se čte co 2 s, dokud se 2× po sobě neshodne.
- POZN.: počet
.ag-rowse „zastropuje" (typicky ~153) kvůli virtuálnímu renderu — NENÍ to skutečný počet záznamů. Slouží jen jako signál „data jsou". Export do CSV ale vyexportuje VŠECHNY řádky (ověřeno: různé velikosti CSV).
6.2 „Fetching Data" / spinner — NEPLATÍ pro tuto stránku
- Na test-results NENÍ text „Fetching Data" (ten je na samples reportu).
<loading-bar>jen problikne při route-loadu → nespoléhat. Signál =.ag-row.
6.3 Tři tečky (export) — na stránce jsou DVA <ag-export>
- 2×
<ag-export>(1 skrytý), 3× ikonamore_horiz. Proto filtr na viditelnost: ✅page.locator("ag-export button:visible", has_text="more_horiz").first.click()
6.4 „Export to CSV" — v DOM jsou DVĚ položky
- 2×
mdl-menu-item„Export to CSV" (1 skrytá). Proto: ✅page.locator("mdl-menu-item:visible", has_text="Export to CSV").first.click()- ❌
get_by_text("Export to CSV")→ strict mode violation (2 elementy).
- ❌
6.5 Prázdné centrum (ověřeno přes Chrome MCP na centru 930551)
- AG Grid při 0 záznamech zobrazí no-rows overlay s textem „No Data".
- Struktura:
.ag-overlay→.ag-overlay-panel→.ag-overlay-no-rows-wrapper→<span>No Data</span>. - ⚠️ Třída NENÍ
.ag-overlay-no-rows-center(chybný předpoklad, nikdy nezabral) — správně je.ag-overlay-no-rows-wrapper. - ⚠️ Text „No Data" NENÍ v
.ag-body-viewport(ten je prázdný,height: 1px). - ⚠️ Na stránce jsou 2 overlaye (1 skrytý, 1 viditelný) → kontrola
viditelnosti
offsetParent !== null. - Detekce (KROK 2):
() => { if (document.querySelectorAll('div.ag-row').length > 0) return false; return [...document.querySelectorAll('.ag-overlay-no-rows-wrapper')] .some(e => e.offsetParent !== null); } - KROK 2 čeká na
.ag-rowNEBO tuto detekci → prázdné centrum necheká zbytečně 120 s a export se přeskočí.
7. Login logika (sdílená napříč Covance skripty)
page.goto(LOGIN_URL)
page.wait_for_load_state("networkidle")
if not page.get_by_label("Email").is_visible():
return # session aktivní → login přeskočit
# jinak: Email → Next → Password → Verify → wait redirect (code= zmizí z URL)
- Proč
is_visible()a ne kontrola URL: pogoto(LOGIN_URL)zůstane URLxsp.covance.comi po redirectu, takže URL test je nespolehlivý. is_visible()neháže výjimku — když pole není, vrátíFalse.
8. Chrome flagy proti „Restore pages" / broken session
--disable-restore-session-state # neobnovovat předchozí session
--disable-session-crashed-bubble # potlačit "Chromium didn't shut down correctly"
9. Robustnost smyčky
- Každý report je v
try/except→ chyba u jednoho nezastaví zbytek. - Na konci souhrn:
hotovo X/34+ seznamSELHALA centra: site/typ, ….
10. Možná budoucí rozšíření
- Další studie / centra: přidat položku do
STUDIES. - Další typ reportu: přidat položku do
REPORT_TYPES(slug + suffix). - Ověření počtu: počet
.ag-rowse loguje — POZOR, je zastropený virtuálním renderem, takže ho nelze porovnávat s počtem řádků v CSV (CSV má všechny).
11. Příbuzné skripty (stejná složka / portál)
| Skript | Co stahuje |
|---|---|
download_samples_report_v1.1.py |
All Samples (sampletracking, čeká na „Fetching Data") |
download_kit_inventory_v2.1.py |
Kit inventory (on-hand expiration) |
download_equeries_report_v1.1.py |
eQuery reporty (zdroj SITE_IDS pro 36940) |
download_test_results_v1.1.py |
tento — Test Results (Standard + Microbiology, 2 studie) |
Všechny sdílejí: persistent profile, login s is_visible() checkem,
ag-export + „Export to CSV" pattern.