192 lines
7.1 KiB
Python
192 lines
7.1 KiB
Python
from selenium import webdriver
|
|
from selenium.webdriver.chrome.options import Options
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
from selenium.common.exceptions import TimeoutException, WebDriverException
|
|
from dotenv import load_dotenv
|
|
from email.message import EmailMessage
|
|
from urllib.parse import urlparse
|
|
import time
|
|
import os
|
|
import smtplib
|
|
import requests
|
|
|
|
# Umbrales por red (en segundos)
|
|
UMBRAL_POR_RED = {
|
|
"3G": 4,
|
|
"4G": 3,
|
|
"WiFi": 2,
|
|
"sin_limitaciones": 2
|
|
}
|
|
|
|
# Perfiles de red con latencia, descarga, subida y tipo conexión
|
|
PERFILES_RED = {
|
|
"3G": {"latency": 150, "download": 3, "upload": 3, "type": "cellular3g"},
|
|
"4G": {"latency": 50, "download": 40, "upload": 40, "type": "cellular4g"},
|
|
"WiFi": {"latency": 20, "download": 150, "upload": 150, "type": "wifi"},
|
|
"sin_limitaciones": {"latency": 0, "download": 0, "upload": 0, "type": "sin_limitaciones"}
|
|
}
|
|
|
|
URL_TEST = "https://www.gugler.com.ar"
|
|
logs = []
|
|
resumen_tabla = []
|
|
|
|
def enviar_email(contenido, asunto="Reporte de performance web - Selenium", destinatario="exequiel84@gmail.com"):
|
|
load_dotenv()
|
|
remitente = os.getenv("EMAIL")
|
|
password = os.getenv("PASSWORD")
|
|
|
|
if not remitente or not password:
|
|
log("❌ ERROR: EMAIL o PASSWORD no definidos en el archivo .env")
|
|
return
|
|
|
|
if not destinatario:
|
|
destinatario = remitente
|
|
|
|
msg = EmailMessage()
|
|
msg['Subject'] = asunto
|
|
msg['From'] = remitente
|
|
msg['To'] = destinatario
|
|
msg.set_content(contenido)
|
|
|
|
try:
|
|
log("\n📤 Enviando correo ...")
|
|
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
|
|
smtp.login(remitente, password)
|
|
smtp.send_message(msg)
|
|
log("✅ Correo enviado exitosamente.")
|
|
except Exception as e:
|
|
log(f"❌ Error al enviar el correo: {e}")
|
|
|
|
def log(msg):
|
|
print(msg)
|
|
logs.append(msg)
|
|
|
|
def limpiar_cache(driver):
|
|
driver.execute_cdp_cmd('Network.clearBrowserCache', {})
|
|
driver.execute_cdp_cmd('Network.clearBrowserCookies', {})
|
|
log("🧹 Caché y cookies limpiadas.")
|
|
time.sleep(4)
|
|
|
|
def emular_red(driver, latencia_ms, descarga_mbps, subida_mbps, tipo_conexion):
|
|
if tipo_conexion == "sin_limitaciones":
|
|
driver.execute_cdp_cmd("Network.disable", {})
|
|
return
|
|
driver.execute_cdp_cmd("Network.enable", {})
|
|
driver.execute_cdp_cmd("Network.emulateNetworkConditions", {
|
|
"offline": False,
|
|
"latency": latencia_ms,
|
|
"downloadThroughput": descarga_mbps * 1_000_000,
|
|
"uploadThroughput": subida_mbps * 1_000_000,
|
|
"connectionType": tipo_conexion,
|
|
})
|
|
|
|
def medir_carga(driver, umbral_total, nombre_red):
|
|
try:
|
|
driver.execute_cdp_cmd("Network.setExtraHTTPHeaders", {"headers": {"Cache-Control": "no-store"}})
|
|
driver.get(URL_TEST)
|
|
WebDriverWait(driver, 60).until(lambda d: d.execute_script("return document.readyState") == "complete")
|
|
WebDriverWait(driver, 10).until(lambda d: d.execute_script(
|
|
"return window.performance.getEntriesByType('resource').filter(e => e.responseEnd == 0).length == 0"))
|
|
|
|
timing = driver.execute_script("return window.performance.timing")
|
|
tiempo_total = (timing.get('loadEventEnd', 0) - timing.get('navigationStart', 0)) / 1000
|
|
|
|
log(f"\n⏱ Tiempo de carga total: {tiempo_total:.2f} s")
|
|
log("✅ Dentro del umbral total" if tiempo_total <= umbral_total else f"⚠️ Superó el umbral total de {umbral_total}s")
|
|
|
|
recursos = driver.execute_script("return window.performance.getEntriesByType('resource')")
|
|
recursos_rotos = 0
|
|
url_base = urlparse(URL_TEST).netloc
|
|
recursos_filtrados = []
|
|
|
|
for r in recursos:
|
|
url_recurso = r.get('name', '')
|
|
host_recurso = urlparse(url_recurso).netloc
|
|
recurso_url = urlparse(url_recurso).path if host_recurso == url_base else url_recurso
|
|
recursos_filtrados.append({
|
|
"duracion": r.get('duration', 0),
|
|
"url": recurso_url,
|
|
"tipo": r.get('initiatorType', 'desconocido')
|
|
})
|
|
|
|
log(f"\n📦 {len(recursos)} Recursos individuales (ordenados por duración):")
|
|
for r in sorted(recursos_filtrados, key=lambda x: x['duracion'], reverse=True):
|
|
dur_segundos = r['duracion'] / 1000
|
|
url_recurso = r['url']
|
|
if url_recurso.startswith("/"):
|
|
url_completa = URL_TEST.rstrip("/") + url_recurso
|
|
elif url_recurso.startswith("http"):
|
|
url_completa = url_recurso
|
|
else:
|
|
continue
|
|
|
|
try:
|
|
resp = requests.head(url_completa, timeout=5, allow_redirects=True)
|
|
status = resp.status_code
|
|
ok = status in [200, 304]
|
|
except Exception:
|
|
status = "ERR"
|
|
ok = False
|
|
|
|
if not ok:
|
|
recursos_rotos += 1
|
|
|
|
icono = "✅" if ok and dur_segundos <= 1 else "⚠️"
|
|
estado_http = f"HTTP {status}"
|
|
log(f" {icono} {dur_segundos:.2f}s [{r['tipo']}] - {url_recurso} → {estado_http}")
|
|
|
|
resumen_tabla.append({
|
|
"red": nombre_red,
|
|
"tiempo_total": tiempo_total,
|
|
"umbral": umbral_total,
|
|
"recursos": len(recursos),
|
|
"rotos": recursos_rotos,
|
|
"supero_umbral": tiempo_total > umbral_total
|
|
})
|
|
|
|
except TimeoutException:
|
|
log("⏰ Timeout esperando que el DOM termine de cargar.")
|
|
except WebDriverException as e:
|
|
log(f"❌ Error durante la prueba: {e}")
|
|
|
|
def mostrar_tabla_resumen():
|
|
log("\n📊 Tabla resumen final:")
|
|
header = f"{'Red':<25} {'Tiempo (s)':<12} {'Umbral (s)':<12} {'Recursos':<10} {'Rotos':<8} {'Estado'}"
|
|
log(header)
|
|
log("-" * len(header))
|
|
for fila in resumen_tabla:
|
|
estado = "⚠️ Lento" if fila["supero_umbral"] else "✅ Ok"
|
|
log(f"{fila['red']:<25} {fila['tiempo_total']:<12.2f} {fila['umbral']:<12} {fila['recursos']:<10} {fila['rotos']:<8} {estado}")
|
|
|
|
def main():
|
|
options = Options()
|
|
# options.add_argument("--headless")
|
|
options.add_argument("--incognito")
|
|
options.add_argument("--disable-gpu")
|
|
options.add_argument("--enable-logging")
|
|
|
|
driver = webdriver.Remote(
|
|
command_executor='http://localhost:4444/wd/hub',
|
|
options=options
|
|
)
|
|
driver.set_page_load_timeout(60)
|
|
try:
|
|
for nombre_red, params in PERFILES_RED.items():
|
|
if nombre_red in UMBRAL_POR_RED:
|
|
log(f"\n=== 🌐 Probando conexión: {nombre_red} ===")
|
|
try:
|
|
driver.get("https://www.google.com")
|
|
limpiar_cache(driver)
|
|
emular_red(driver, params['latency'], params['download'], params['upload'], params['type'])
|
|
medir_carga(driver, UMBRAL_POR_RED[nombre_red], nombre_red)
|
|
except Exception as e:
|
|
log(f"❌ Error durante la prueba con {nombre_red}: {str(e)}")
|
|
mostrar_tabla_resumen()
|
|
finally:
|
|
driver.quit()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
contenido_email = "\n".join(logs)
|
|
enviar_email(contenido_email)
|