170 lines
7.4 KiB
Python
170 lines
7.4 KiB
Python
"""Explorační skript — přihlášení do EvaMed CRF, načtení všech formulářů, nalezení AE."""
|
|
|
|
import asyncio
|
|
from playwright.async_api import async_playwright
|
|
|
|
BASE_URL = "https://prod.evamed.com/etude/soft/index.php"
|
|
LOGIN_URL = "https://prod.evamed.com/etude/soft/index.php?module=authentification&class=login&client=myopowers-dry"
|
|
LOGIN = "vbuzalka"
|
|
PASSWORD = "Vlado9674+"
|
|
SCREENSHOTS_DIR = "screenshots"
|
|
|
|
|
|
async def main():
|
|
async with async_playwright() as p:
|
|
browser = await p.chromium.launch(headless=False)
|
|
context = await browser.new_context(viewport={"width": 1400, "height": 900})
|
|
page = await context.new_page()
|
|
|
|
# 1. Login
|
|
await page.goto(LOGIN_URL)
|
|
await page.wait_for_load_state("networkidle")
|
|
await page.locator('#login').fill(LOGIN)
|
|
await page.locator('input[type="password"]').first.fill(PASSWORD)
|
|
await page.click('text=Connection')
|
|
await page.wait_for_load_state("networkidle")
|
|
print("Logged in")
|
|
|
|
# 2. Go to Forms list
|
|
await page.goto(f"{BASE_URL}?module=monitoring&class=formslisting")
|
|
await page.wait_for_load_state("networkidle")
|
|
print("Forms list loaded (page 1)")
|
|
|
|
# 3. Switch to ALL records
|
|
await page.select_option('select[name="l"]', 'ALL')
|
|
print("Switched to ALL, waiting for all rows to load...")
|
|
|
|
await page.wait_for_function(
|
|
"() => document.querySelectorAll('tr').length > 3200",
|
|
timeout=120000
|
|
)
|
|
print(f"All rows loaded")
|
|
|
|
# 4. Count total rows and find AE rows
|
|
stats = await page.evaluate("""() => {
|
|
const rows = document.querySelectorAll('tr');
|
|
let totalRows = rows.length;
|
|
let aeRows = [];
|
|
let formCodes = {};
|
|
|
|
rows.forEach((row, idx) => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
cells.forEach(cell => {
|
|
// collect all unique form codes from the Formcode column
|
|
});
|
|
// Look for AE in any cell
|
|
const cellTexts = cells.map(c => c.innerText.trim());
|
|
// Formcode is typically column index 8 based on the header
|
|
if (cells.length > 8) {
|
|
const formcode = cells[8]?.innerText?.trim();
|
|
formCodes[formcode] = (formCodes[formcode] || 0) + 1;
|
|
if (formcode === 'AE') {
|
|
aeRows.push({
|
|
rowIndex: idx,
|
|
subject: cells[0]?.innerText?.trim(),
|
|
formcode: formcode,
|
|
formName: cells[9]?.innerText?.trim(),
|
|
allCells: cellTexts,
|
|
links: Array.from(row.querySelectorAll('a')).map(a => ({
|
|
href: a.getAttribute('href'),
|
|
title: a.title || '',
|
|
text: a.innerText.trim().substring(0, 50)
|
|
}))
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
return { totalRows, aeCount: aeRows.length, aeRows: aeRows.slice(0, 5), formCodes };
|
|
}""")
|
|
|
|
print(f"Total rows: {stats['totalRows']}")
|
|
print(f"AE rows found: {stats['aeCount']}")
|
|
print(f"Form codes: {stats['formCodes']}")
|
|
|
|
if stats['aeRows']:
|
|
print(f"\nFirst AE row sample:")
|
|
ae = stats['aeRows'][0]
|
|
print(f" Subject: {ae['subject']}")
|
|
print(f" All cells: {ae['allCells']}")
|
|
print(f" Links: {ae['links']}")
|
|
|
|
# 5. Open first AE form
|
|
for link in ae['links']:
|
|
if link.get('href') and 'id=' in link['href']:
|
|
ae_url = link['href']
|
|
if not ae_url.startswith('http'):
|
|
ae_url = f"https://prod.evamed.com/etude/soft/{ae_url}"
|
|
print(f"\nOpening AE form: {ae_url}")
|
|
await page.goto(ae_url)
|
|
await page.wait_for_load_state("networkidle")
|
|
await page.screenshot(path=f"{SCREENSHOTS_DIR}/05_ae_form.png", full_page=True)
|
|
print("Screenshot: AE form")
|
|
|
|
# Extract all fields from the form
|
|
fields = await page.evaluate("""() => {
|
|
// Try input-group pattern
|
|
const groups = document.querySelectorAll('.input-group');
|
|
let inputGroupFields = Array.from(groups).map(g => ({
|
|
html: g.outerHTML.substring(0, 800),
|
|
text: g.innerText.trim().substring(0, 300)
|
|
}));
|
|
|
|
// Try label/value pattern in tableauFormulaire
|
|
const tableFields = [];
|
|
document.querySelectorAll('.tableauFormulaire td, .tableauFormulaire th').forEach(el => {
|
|
tableFields.push({
|
|
tag: el.tagName,
|
|
className: el.className,
|
|
text: el.innerText.trim().substring(0, 200)
|
|
});
|
|
});
|
|
|
|
// Try all form inputs
|
|
const inputs = [];
|
|
document.querySelectorAll('input, select, textarea').forEach(el => {
|
|
inputs.push({
|
|
type: el.type,
|
|
name: el.name,
|
|
id: el.id,
|
|
value: el.value?.substring(0, 200),
|
|
className: el.className
|
|
});
|
|
});
|
|
|
|
return { inputGroupFields, tableFields: tableFields.slice(0, 50), inputs: inputs.slice(0, 50) };
|
|
}""")
|
|
|
|
print(f"\nInput groups: {len(fields['inputGroupFields'])}")
|
|
for i, f in enumerate(fields['inputGroupFields'][:10]):
|
|
print(f" [{i}] {f['text'][:120]}")
|
|
|
|
print(f"\nTable fields: {len(fields['tableFields'])}")
|
|
for i, f in enumerate(fields['tableFields'][:20]):
|
|
print(f" [{i}] <{f['tag']} class='{f['className']}'> {f['text'][:100]}")
|
|
|
|
print(f"\nForm inputs: {len(fields['inputs'])}")
|
|
for i, f in enumerate(fields['inputs'][:20]):
|
|
print(f" [{i}] {f['type']} name={f['name']} id={f['id']} val={f['value'][:60] if f['value'] else ''}")
|
|
|
|
# Save full form HTML for analysis
|
|
form_html = await page.content()
|
|
with open(f"{SCREENSHOTS_DIR}/05_ae_form_full.html", "w", encoding="utf-8") as f:
|
|
f.write(form_html)
|
|
print("Saved: full AE form HTML")
|
|
break
|
|
else:
|
|
print("NO AE ROWS FOUND!")
|
|
await page.screenshot(path=f"{SCREENSHOTS_DIR}/04_all_forms.png", full_page=False)
|
|
# Dump all unique form codes for debugging
|
|
print("Available form codes:", list(stats['formCodes'].keys())[:30])
|
|
|
|
await browser.close()
|
|
print("Done")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import os
|
|
os.makedirs(SCREENSHOTS_DIR, exist_ok=True)
|
|
asyncio.run(main())
|