fix(login,download): login direct pe goapp, descarcare doar a documentului nou
- BT a mutat login-ul (09.2026): go.bancatransilvania.ro face 302 spre marketing; formularul e pe goapp.bancatransilvania.ro, acelasi tab, fara popup. - Daca formularul nu apare: eroare explicita cu URL/titlu + screenshot/HTML. - scripts/check_login_page.py: verifica pagina de login fara credentiale. - Download: asteapta documentul nou din "Recente"; export gol -> [SKIP], nu timeout. - Screenshot la eroare facut inainte de oprirea Playwright. - opencode.json: agentii opencode nu pot citi .env. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DxPhZABSUf1RJXRWtwecqC
This commit is contained in:
182
scripts/check_login_page.py
Normal file
182
scripts/check_login_page.py
Normal file
@@ -0,0 +1,182 @@
|
||||
"""
|
||||
Verifica daca pagina de login BT e inca la fel (campuri user/parola/submit).
|
||||
|
||||
Fara credentiale, fara .env: doar deschide pagina de login ca scraper-ul,
|
||||
o observa si iese cu cod 0 daca formularul e intact, altfel 1 + motivul.
|
||||
Nu completeaza campuri si nu submite nimic.
|
||||
|
||||
Chromium e lansat identic cu btgo_scraper.py (noul mod headless
|
||||
--headless=new + UA de Chrome normal), altfel WAF-ul Akamai al BT raspunde
|
||||
cu Access Denied. Nu folosim networkidle (nu se atinge niciodata pe site-ul
|
||||
BT) -> domcontentloaded + asteptari pe selector.
|
||||
|
||||
Nota: lansarea browserului e duplicata din btgo_scraper.run() pentru ca
|
||||
acolo e inline si btgo_scraper importa config (care citeste .env). Daca
|
||||
lansarea va fi extrasa intr-un helper fara config, scriptul il poate importa.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
|
||||
|
||||
# Aceleasi intrari ca in btgo_scraper.login() (ordinea conteaza).
|
||||
LOGIN_ENTRY_URLS = [
|
||||
"https://goapp.bancatransilvania.ro/",
|
||||
"https://go.bancatransilvania.ro/",
|
||||
]
|
||||
|
||||
USER_SELECTORS = ["input#user", "input[placeholder='ID logare']"]
|
||||
PASSWORD_SELECTORS = ["input#password", "input[type='password']"]
|
||||
SUBMIT_SELECTORS = [
|
||||
"input[type='submit']",
|
||||
"button[type='submit']",
|
||||
"input[value*='Autentific']",
|
||||
]
|
||||
|
||||
DATA_DIR = Path("data")
|
||||
|
||||
|
||||
def launch(p):
|
||||
"""Lanseaza Chromium exact ca btgo_scraper.run() (WAF-safe)."""
|
||||
browser = p.chromium.launch(
|
||||
headless=False,
|
||||
slow_mo=0,
|
||||
args=[
|
||||
"--window-size=1366,768",
|
||||
"--disable-gpu",
|
||||
"--disable-dev-shm-usage",
|
||||
"--disable-extensions",
|
||||
"--disable-background-networking",
|
||||
"--disable-renderer-backgrounding",
|
||||
"--disable-features=Translate",
|
||||
"--headless=new",
|
||||
],
|
||||
)
|
||||
context = browser.new_context(
|
||||
viewport={"width": 1366, "height": 768},
|
||||
user_agent=(
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/130.0.0.0 Safari/537.36"
|
||||
),
|
||||
)
|
||||
return browser, context
|
||||
|
||||
|
||||
def first_visible(page, selectors, timeout=1000):
|
||||
"""Primul selector din lista care are un element vizibil, sau None."""
|
||||
for sel in selectors:
|
||||
try:
|
||||
el = page.locator(sel).first
|
||||
if el.count() and el.is_visible(timeout=timeout):
|
||||
return sel
|
||||
except Exception:
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
def dump_diag(page):
|
||||
"""Salveaza HTML + screenshot pentru diagnostic. Returneaza caile scrise."""
|
||||
written = []
|
||||
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
try:
|
||||
DATA_DIR.mkdir(exist_ok=True)
|
||||
except Exception:
|
||||
return written
|
||||
try:
|
||||
html_path = DATA_DIR / f"check_login_page_{ts}.html"
|
||||
html_path.write_text(page.content(), encoding="utf-8")
|
||||
written.append(html_path)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
shot_path = DATA_DIR / f"check_login_page_{ts}.png"
|
||||
page.screenshot(path=str(shot_path))
|
||||
written.append(shot_path)
|
||||
except Exception:
|
||||
pass
|
||||
return written
|
||||
|
||||
|
||||
def check_page(page, url):
|
||||
"""Navigheaza la `url` si inspecteaza formularul. Returneaza un dict."""
|
||||
info = {
|
||||
"ok": False,
|
||||
"url": url,
|
||||
"final_url": None,
|
||||
"title": None,
|
||||
"user": None,
|
||||
"password": None,
|
||||
"submit": None,
|
||||
"error": None,
|
||||
}
|
||||
print(f"[check] {url}")
|
||||
|
||||
try:
|
||||
page.goto(url, wait_until="domcontentloaded", timeout=30000)
|
||||
except Exception as e:
|
||||
info["error"] = f"goto a esuat: {e}"
|
||||
print(f" [WARN] {info['error']}")
|
||||
return info
|
||||
|
||||
try:
|
||||
page.wait_for_selector(
|
||||
", ".join(USER_SELECTORS), timeout=60000, state="visible"
|
||||
)
|
||||
except PlaywrightTimeout:
|
||||
info["final_url"] = page.url
|
||||
info["title"] = page.title()
|
||||
info["error"] = "formularul de login (input#user) nu a aparut"
|
||||
print(f" [WARN] {info['error']} (URL final: {info['final_url']})")
|
||||
return info
|
||||
|
||||
info["final_url"] = page.url
|
||||
info["title"] = page.title()
|
||||
info["user"] = first_visible(page, USER_SELECTORS)
|
||||
info["password"] = first_visible(page, PASSWORD_SELECTORS)
|
||||
info["submit"] = first_visible(page, SUBMIT_SELECTORS)
|
||||
info["ok"] = bool(info["user"] and info["password"] and info["submit"])
|
||||
|
||||
print(f" URL final: {info['final_url']}")
|
||||
print(f" titlu: {info['title']!r}")
|
||||
print(f" user: {info['user']!r}")
|
||||
print(f" parola: {info['password']!r}")
|
||||
print(f" submit: {info['submit']!r}")
|
||||
return info
|
||||
|
||||
|
||||
def main():
|
||||
with sync_playwright() as p:
|
||||
browser, context = launch(p)
|
||||
try:
|
||||
page = context.new_page()
|
||||
last = None
|
||||
for url in LOGIN_ENTRY_URLS:
|
||||
info = check_page(page, url)
|
||||
if info["ok"]:
|
||||
print("[OK] Pagina de login e intacta "
|
||||
"(campuri user/parola/submit gasite).")
|
||||
return 0
|
||||
last = info
|
||||
|
||||
written = dump_diag(page)
|
||||
missing = [k for k in ("user", "password", "submit")
|
||||
if not last.get(k)]
|
||||
print("[FAIL] Pagina de login BT s-a schimbat.")
|
||||
print(f" URL final: {last.get('final_url')}, "
|
||||
f"titlu: {last.get('title')!r}")
|
||||
if last.get("error"):
|
||||
print(f" Motiv: {last['error']}")
|
||||
if missing:
|
||||
print(f" Campuri lipsa: {', '.join(missing)}")
|
||||
for path in written:
|
||||
print(f" Dovezi: {path}")
|
||||
return 1
|
||||
finally:
|
||||
browser.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user