primer commit
This commit is contained in:
commit
2be35d7e55
17 files changed
+2709
No files matched your search
@@ -0,0 +1,325 @@
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import time
|
||||
import base64
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from get_token import (
|
||||
SOL_URL, MENU_URL, TOKEN_FILE, SCREENSHOT_DIR,
|
||||
RUC, USER, PASSWORD,
|
||||
fill_login_form, save_screenshot, save_token,
|
||||
check_for_token, navigate_sol_menu,
|
||||
click_menu_item_by_id, extract_token_from_menu,
|
||||
)
|
||||
|
||||
TEST_DIR = SCREENSHOT_DIR
|
||||
TEST_DIR.mkdir(exist_ok=True)
|
||||
|
||||
USER_AGENT = (
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/120.0.0.0 Safari/537.36"
|
||||
)
|
||||
|
||||
BROWSER_ARGS = [
|
||||
"--disable-blink-features=AutomationControlled",
|
||||
"--disable-popup-blocking",
|
||||
"--no-sandbox",
|
||||
"--disable-web-security",
|
||||
"--disable-features=IsolateOrigins,site-per-process",
|
||||
"--window-size=1280,800",
|
||||
"--start-maximized",
|
||||
]
|
||||
|
||||
|
||||
def captura(page, tag, nombre):
|
||||
safe = f"{tag}_{nombre}"
|
||||
page.screenshot(path=str(TEST_DIR / f"{safe}.png"))
|
||||
|
||||
|
||||
def _salto_linea(texto, ancho=100):
|
||||
for i in range(0, len(texto), ancho):
|
||||
print(f" {texto[i:i+ancho]}")
|
||||
|
||||
|
||||
def _login_si_necesario(page, tag):
|
||||
page.wait_for_load_state("networkidle")
|
||||
has_inputs = len(page.locator("input[type='password']").all()) > 0
|
||||
necesita_login = has_inputs or any(
|
||||
k in page.url.lower() for k in ["login", "autentica", "auth"]
|
||||
)
|
||||
if not necesita_login:
|
||||
print(" No se detectó login")
|
||||
return True
|
||||
|
||||
print(" Login detectado. Rellenando credenciales...")
|
||||
fill_login_form(page)
|
||||
captura(page, tag, "form_rellenado")
|
||||
|
||||
page.keyboard.press("Enter")
|
||||
try:
|
||||
page.wait_for_load_state("networkidle", timeout=30000)
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Timeout post-login: {e}")
|
||||
page.wait_for_timeout(3000)
|
||||
captura(page, tag, "post_login")
|
||||
print(f" URL post-login: {page.url}")
|
||||
return True
|
||||
|
||||
|
||||
def _buscar_token_en_pagina(page, tag):
|
||||
time.sleep(2)
|
||||
token = check_for_token(page)
|
||||
if token:
|
||||
return token
|
||||
|
||||
token = navigate_sol_menu(page)
|
||||
if token:
|
||||
return token
|
||||
|
||||
token = extract_token_from_menu(page)
|
||||
return token
|
||||
|
||||
|
||||
def _navegar_con_cookies(page, url, tag):
|
||||
page.goto(url, wait_until="domcontentloaded")
|
||||
captura(page, tag, "navegacion")
|
||||
print(f" URL tras navegar: {page.url}")
|
||||
|
||||
|
||||
# ─── ESTRATEGIAS ─────────────────────────────────────────────
|
||||
|
||||
|
||||
def estrategia_1_fixed_popup(context, page):
|
||||
tag = "e1"
|
||||
print("\n" + "=" * 60)
|
||||
print("ESTRATEGIA 1: Popup con --disable-popup-blocking + event listener")
|
||||
print("=" * 60)
|
||||
|
||||
page.goto(SOL_URL, wait_until="domcontentloaded")
|
||||
captura(page, tag, "sol_home")
|
||||
|
||||
popup_found = [None]
|
||||
got_popup = [False]
|
||||
|
||||
def on_page(new_page):
|
||||
if not got_popup[0]:
|
||||
print(f" 📌 Página detectada: {new_page.url[:100]}")
|
||||
popup_found[0] = new_page
|
||||
got_popup[0] = True
|
||||
|
||||
page.context().on("page", on_page)
|
||||
|
||||
with page.expect_popup() as popup_info:
|
||||
page.evaluate("tramiteConsulta()")
|
||||
|
||||
try:
|
||||
pup = popup_info.value
|
||||
pup.wait_for_load_state("domcontentloaded", timeout=20000)
|
||||
print(f" Popup URL: {pup.url}")
|
||||
captura(pup, tag, "popup")
|
||||
|
||||
if "chrome-error" in pup.url:
|
||||
print(" ⚠️ Popup en chrome-error. Reintentando recarga...")
|
||||
try:
|
||||
pup.wait_for_load_state("domcontentloaded", timeout=20000)
|
||||
except:
|
||||
pass
|
||||
captura(pup, tag, "popup_retry")
|
||||
if "chrome-error" in pup.url:
|
||||
print(" ❌ Sigue en chrome-error tras recarga")
|
||||
print(f" URL final: {pup.url}")
|
||||
return None
|
||||
|
||||
_login_si_necesario(pup, tag)
|
||||
token = _buscar_token_en_pagina(pup, tag)
|
||||
return token
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Error con popup: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def estrategia_2_direct_menu(context, page):
|
||||
tag = "e2"
|
||||
print("\n" + "=" * 60)
|
||||
print("ESTRATEGIA 2: Menú directo con sesión desde SOL")
|
||||
print("=" * 60)
|
||||
|
||||
page.goto(SOL_URL, wait_until="domcontentloaded")
|
||||
captura(page, tag, "sol_home")
|
||||
|
||||
_navegar_con_cookies(page, MENU_URL, tag)
|
||||
|
||||
if not _login_si_necesario(page, tag):
|
||||
return None
|
||||
|
||||
token = _buscar_token_en_pagina(page, tag)
|
||||
return token
|
||||
|
||||
|
||||
def estrategia_3_direct_login(context, page):
|
||||
tag = "e3"
|
||||
print("\n" + "=" * 60)
|
||||
print("ESTRATEGIA 3: Login directo al menú (sin SOL)")
|
||||
print("=" * 60)
|
||||
|
||||
_navegar_con_cookies(page, MENU_URL, tag)
|
||||
|
||||
if not _login_si_necesario(page, tag):
|
||||
return None
|
||||
|
||||
token = _buscar_token_en_pagina(page, tag)
|
||||
return token
|
||||
|
||||
|
||||
def estrategia_4_popup_url_directo(context, page):
|
||||
tag = "e4"
|
||||
print("\n" + "=" * 60)
|
||||
print("ESTRATEGIA 4: Extraer URL del popup y navegar directo")
|
||||
print("=" * 60)
|
||||
|
||||
page.goto(SOL_URL, wait_until="domcontentloaded")
|
||||
captura(page, tag, "sol_home")
|
||||
|
||||
try:
|
||||
popup_url = page.evaluate("""() => {
|
||||
const fn = tramiteConsulta.toString();
|
||||
const match = fn.match(/window\\.open\\(['"]([^'"]+)['"]/);
|
||||
return match ? match[1] : null;
|
||||
}""")
|
||||
if popup_url:
|
||||
if popup_url.startswith("/"):
|
||||
from urllib.parse import urljoin
|
||||
popup_url = urljoin(SOL_URL, popup_url)
|
||||
print(f" URL del popup: {popup_url}")
|
||||
else:
|
||||
print(" No se pudo extraer URL")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f" Error extrayendo URL: {e}")
|
||||
return None
|
||||
|
||||
_navegar_con_cookies(page, popup_url, tag)
|
||||
|
||||
if not _login_si_necesario(page, tag):
|
||||
return None
|
||||
|
||||
token = _buscar_token_en_pagina(page, tag)
|
||||
return token
|
||||
|
||||
|
||||
# ─── CONFIGURACIONES DE LANZAMIENTO ──────────────────────────
|
||||
|
||||
|
||||
def lanzar_chrome(p, channel=None, extra_args=None):
|
||||
"""Lanza navegador con la configuracion dada."""
|
||||
args = list(BROWSER_ARGS)
|
||||
if extra_args:
|
||||
args.extend(extra_args)
|
||||
|
||||
kwargs = {
|
||||
"headless": True,
|
||||
"args": args,
|
||||
}
|
||||
if channel:
|
||||
kwargs["channel"] = channel
|
||||
print(f" Lanzando: {channel} (headless)")
|
||||
else:
|
||||
print(f" Lanzando: chromium empaquetado (headless)")
|
||||
|
||||
browser = p.chromium.launch(**kwargs)
|
||||
|
||||
context = browser.new_context(
|
||||
viewport={"width": 1280, "height": 800},
|
||||
locale="es-PE",
|
||||
timezone_id="America/Lima",
|
||||
user_agent=USER_AGENT,
|
||||
no_viewport=False,
|
||||
ignore_https_errors=True,
|
||||
)
|
||||
|
||||
page = context.new_page()
|
||||
page.set_default_timeout(90000)
|
||||
|
||||
return browser, context, page
|
||||
|
||||
|
||||
def ejecutar_escenario(p, nombre_browser, channel, extra_args):
|
||||
"""Ejecuta todas las estrategias con un navegador/configuracion."""
|
||||
print(f"\n{'#'*60}")
|
||||
print(f"# ESCENARIO: {nombre_browser}")
|
||||
print(f"{'#'*60}")
|
||||
|
||||
browser, context, page = lanzar_chrome(p, channel, extra_args)
|
||||
|
||||
token = None
|
||||
estrategias = [
|
||||
("1_fixed_popup", estrategia_1_fixed_popup),
|
||||
("2_direct_menu", estrategia_2_direct_menu),
|
||||
("3_direct_login", estrategia_3_direct_login),
|
||||
("4_popup_url_directo", estrategia_4_popup_url_directo),
|
||||
]
|
||||
|
||||
for nombre, fn in estrategias:
|
||||
print()
|
||||
try:
|
||||
token = fn(context, page)
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Excepción en {nombre}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
token = None
|
||||
|
||||
if token:
|
||||
print(f"\n✅ Token obtenido con '{nombre}' en escenario '{nombre_browser}'!")
|
||||
return token
|
||||
else:
|
||||
print(f"\n ❌ '{nombre}' falló")
|
||||
|
||||
context.close()
|
||||
browser.close()
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("🔐 TEST HEADLESS TOKEN - SUNAT")
|
||||
print("=" * 60)
|
||||
print(f" RUC: {RUC}")
|
||||
print(f" USER: {USER}")
|
||||
|
||||
if not RUC or not USER or not PASSWORD:
|
||||
print("\n❌ Faltan credenciales en .env (SUNAT_RUC, SUNAT_USER, SUNAT_PASSWORD)")
|
||||
return
|
||||
|
||||
escenarios = [
|
||||
("Chrome real (channel=chrome)", "chrome", None),
|
||||
("Chromium empaquetado", None, None),
|
||||
("Chromium + extra stealth", None, ["--disable-gpu", "--disable-accelerated-2d-canvas"]),
|
||||
]
|
||||
|
||||
with sync_playwright() as p:
|
||||
for nombre_browser, channel, extra_args in escenarios:
|
||||
token = ejecutar_escenario(p, nombre_browser, channel, extra_args)
|
||||
if token:
|
||||
save_token(token)
|
||||
print(f"\n✅ Token guardado en {TOKEN_FILE}")
|
||||
print(f" Primeros 50 chars: {token[:50]}...")
|
||||
|
||||
# Quitar token de prueba, no guardarlo permanentemente
|
||||
if TOKEN_FILE.exists():
|
||||
TOKEN_FILE.unlink()
|
||||
return
|
||||
|
||||
print(f"\n❌ Todas las estrategias y escenarios fallaron.")
|
||||
print(" Revisa screenshots en:", TEST_DIR)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user