browser_detection.py•8.55 kB
"""
Módulo para detectar navegadores disponibles en el sistema.
"""
import os
import platform
import subprocess
from typing import Dict, List, Optional
from pathlib import Path
class BrowserDetection:
"""Detecta navegadores disponibles en el sistema."""
def __init__(self):
self.system = platform.system().lower()
# Rutas comunes de navegadores por sistema operativo
self.browser_paths = {
"windows": {
"chrome": [
r"C:\Program Files\Google\Chrome\Application\chrome.exe",
r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
r"C:\Users\{username}\AppData\Local\Google\Chrome\Application\chrome.exe"
],
"firefox": [
r"C:\Program Files\Mozilla Firefox\firefox.exe",
r"C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
],
"edge": [
r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
r"C:\Program Files\Microsoft\Edge\Application\msedge.exe"
]
},
"linux": {
"chrome": [
"/usr/bin/google-chrome",
"/usr/bin/google-chrome-stable",
"/usr/bin/chromium",
"/usr/bin/chromium-browser",
"/snap/bin/chromium"
],
"firefox": [
"/usr/bin/firefox",
"/usr/bin/firefox-esr",
"/snap/bin/firefox"
]
},
"darwin": { # macOS
"chrome": [
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
],
"firefox": [
"/Applications/Firefox.app/Contents/MacOS/firefox"
],
"safari": [
"/Applications/Safari.app/Contents/MacOS/Safari"
]
}
}
def detect_available_browsers(self) -> Dict[str, Dict]:
"""Detecta todos los navegadores disponibles en el sistema."""
available_browsers = {}
if self.system not in self.browser_paths:
return {"error": f"Sistema operativo no soportado: {self.system}"}
for browser_name, paths in self.browser_paths[self.system].items():
browser_info = self._check_browser(browser_name, paths)
if browser_info["available"]:
available_browsers[browser_name] = browser_info
return available_browsers
def _check_browser(self, browser_name: str, paths: List[str]) -> Dict:
"""Verifica si un navegador específico está disponible."""
browser_info = {
"name": browser_name,
"available": False,
"path": None,
"version": None,
"supported_by_selenium": browser_name in ["chrome", "firefox"]
}
# Verificar rutas comunes
for path in paths:
# Expandir variables de usuario en Windows
if "{username}" in path and self.system == "windows":
import getpass
path = path.format(username=getpass.getuser())
if os.path.exists(path):
browser_info["available"] = True
browser_info["path"] = path
browser_info["version"] = self._get_browser_version(browser_name, path)
break
# Si no se encontró en rutas comunes, intentar comando del sistema
if not browser_info["available"]:
if self._check_command_available(browser_name):
browser_info["available"] = True
browser_info["path"] = f"system_command_{browser_name}"
browser_info["version"] = self._get_browser_version_from_command(browser_name)
return browser_info
def _check_command_available(self, browser_name: str) -> bool:
"""Verifica si el navegador está disponible como comando del sistema."""
commands = {
"chrome": ["google-chrome", "chromium", "chromium-browser"],
"firefox": ["firefox", "firefox-esr"]
}
if browser_name not in commands:
return False
for command in commands[browser_name]:
try:
subprocess.run([command, "--version"],
capture_output=True,
check=True,
timeout=5)
return True
except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
continue
return False
def _get_browser_version(self, browser_name: str, path: str) -> Optional[str]:
"""Obtiene la versión del navegador."""
try:
if browser_name == "chrome":
result = subprocess.run([path, "--version"],
capture_output=True,
text=True,
timeout=5)
if result.returncode == 0:
return result.stdout.strip()
elif browser_name == "firefox":
result = subprocess.run([path, "--version"],
capture_output=True,
text=True,
timeout=5)
if result.returncode == 0:
return result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
pass
return None
def _get_browser_version_from_command(self, browser_name: str) -> Optional[str]:
"""Obtiene la versión del navegador usando comandos del sistema."""
commands = {
"chrome": ["google-chrome", "chromium", "chromium-browser"],
"firefox": ["firefox", "firefox-esr"]
}
if browser_name not in commands:
return None
for command in commands[browser_name]:
try:
result = subprocess.run([command, "--version"],
capture_output=True,
text=True,
timeout=5)
if result.returncode == 0:
return result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
continue
return None
def get_recommended_browser(self) -> str:
"""Devuelve el navegador recomendado basado en disponibilidad."""
available = self.detect_available_browsers()
# Prioridad: Chrome > Firefox
if "chrome" in available:
return "chrome"
elif "firefox" in available:
return "firefox"
else:
return "chrome" # Por defecto, aunque no esté disponible
def check_webdriver_support(self, browser_name: str) -> Dict[str, bool]:
"""Verifica el soporte de WebDriver para un navegador."""
support_info = {
"selenium_support": False,
"webdriver_manager_support": False,
"undetected_chrome_support": False
}
if browser_name == "chrome":
support_info["selenium_support"] = True
support_info["webdriver_manager_support"] = True
support_info["undetected_chrome_support"] = True
elif browser_name == "firefox":
support_info["selenium_support"] = True
support_info["webdriver_manager_support"] = True
support_info["undetected_chrome_support"] = False
return support_info
def get_system_info(self) -> Dict[str, str]:
"""Obtiene información del sistema."""
return {
"system": platform.system(),
"release": platform.release(),
"version": platform.version(),
"machine": platform.machine(),
"processor": platform.processor(),
"architecture": platform.architecture()[0]
}