browser_manager_old.py•11.4 kB
"""
Módulo para gestionar instancias de WebDriver con configuraciones avanzadas.
"""
import os
import random
import tempfile
import shutil
from typing import Optional, Dict, Any
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.firefox.service import Service as FirefoxService
from selenium.webdriver.remote.webdriver import WebDriver
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
try:
import undetected_chromedriver as uc
UNDETECTED_CHROME_AVAILABLE = True
except ImportError:
UNDETECTED_CHROME_AVAILABLE = False
from config import BrowserOptions, ProxyConfig, DetectionEvasionConfig
class WebDriverManager:
"""Gestor de instancias de WebDriver con configuraciones avanzadas."""
def __init__(self):
self.user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
"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",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/121.0"
]
def create_chrome_driver(
self,
browser_options: BrowserOptions,
proxy_config: Optional[ProxyConfig] = None,
detection_evasion: Optional[DetectionEvasionConfig] = None
) -> WebDriver:
"""Crea una instancia de Chrome WebDriver."""
if detection_evasion and detection_evasion.use_undetected_chrome and UNDETECTED_CHROME_AVAILABLE:
return self._create_undetected_chrome(browser_options, proxy_config, detection_evasion)
else:
return self._create_standard_chrome(browser_options, proxy_config, detection_evasion)
def _create_undetected_chrome(
self,
browser_options: BrowserOptions,
proxy_config: Optional[ProxyConfig],
detection_evasion: DetectionEvasionConfig
) -> WebDriver:
"""Crea una instancia de Chrome usando undetected-chromedriver."""
options = uc.ChromeOptions()
# Configurar opciones básicas
self._configure_chrome_options(options, browser_options, proxy_config, detection_evasion)
# Configuraciones específicas para undetected-chromedriver
if detection_evasion.add_experimental_options:
for key, value in detection_evasion.add_experimental_options.items():
options.add_experimental_option(key, value)
# Crear driver con undetected-chromedriver
driver = uc.Chrome(
options=options,
version_main=None, # Detectar automáticamente
headless=browser_options.headless
)
# Configurar tamaño de ventana
if not browser_options.headless:
width = browser_options.window_width
height = browser_options.window_height
if detection_evasion.randomize_viewport:
width += random.randint(-100, 100)
height += random.randint(-50, 50)
driver.set_window_size(width, height)
return driver
def _create_standard_chrome(
self,
browser_options: BrowserOptions,
proxy_config: Optional[ProxyConfig],
detection_evasion: Optional[DetectionEvasionConfig]
) -> WebDriver:
"""Crea una instancia de Chrome estándar."""
options = ChromeOptions()
# Configurar opciones básicas
self._configure_chrome_options(options, browser_options, proxy_config, detection_evasion)
# Configurar servicio
service = ChromeService(ChromeDriverManager().install())
# Crear driver
driver = webdriver.Chrome(service=service, options=options)
driver.user_data_dir = user_data_dir # Guardar para limpieza posterior
# Configurar tamaño de ventana
if not browser_options.headless:
width = browser_options.window_width
height = browser_options.window_height
if detection_evasion and detection_evasion.randomize_viewport:
width += random.randint(-100, 100)
height += random.randint(-50, 50)
driver.set_window_size(width, height)
return driver
def _configure_chrome_options(
self,
options,
browser_options: BrowserOptions,
proxy_config: Optional[ProxyConfig],
detection_evasion: Optional[DetectionEvasionConfig]
):
"""Configura las opciones de Chrome."""
# Modo headless
if browser_options.headless:
options.add_argument("--headless=new")
# Configuraciones básicas
if browser_options.incognito:
options.add_argument("--incognito")
if browser_options.no_sandbox:
options.add_argument("--no-sandbox")
if browser_options.disable_dev_shm_usage:
options.add_argument("--disable-dev-shm-usage")
if browser_options.disable_gpu:
options.add_argument("--disable-gpu")
# User agent
user_agent = browser_options.user_agent
if detection_evasion and detection_evasion.randomize_user_agent:
user_agent = random.choice(self.user_agents)
if user_agent:
options.add_argument(f"--user-agent={user_agent}")
# Configuraciones de contenido
prefs = {}
if browser_options.disable_images:
prefs["profile.managed_default_content_settings.images"] = 2
if browser_options.disable_javascript:
prefs["profile.managed_default_content_settings.javascript"] = 2
# Configuraciones de notificaciones
prefs["profile.default_content_setting_values.notifications"] = 2
prefs["profile.default_content_settings.popups"] = 0
if prefs:
options.add_experimental_option("prefs", prefs)
# Configuraciones de evasión de detección
if detection_evasion:
if detection_evasion.disable_blink_features:
options.add_argument("--disable-blink-features=AutomationControlled")
if detection_evasion.exclude_switches:
options.add_experimental_option("excludeSwitches", detection_evasion.exclude_switches)
# Configuraciones experimentales adicionales
options.add_experimental_option("useAutomationExtension", False)
# Argumentos personalizados
if browser_options.custom_args:
for arg in browser_options.custom_args:
options.add_argument(arg)
# Solución para 'user data directory is already in use'
# Usar un directorio temporal único para cada sesión
user_data_dir = tempfile.mkdtemp()
options.add_argument(f"--user-data-dir={user_data_dir}")
# Añadir soporte para proxy
if proxy_config:
if proxy_config.http:
options.add_argument(f"--proxy-server={proxy_config.http}")
elif proxy_config.https:
options.add_argument(f"--proxy-server={proxy_config.https}")
elif proxy_config.socks:
options.add_argument(f"--proxy-server={proxy_config.socks}")
def create_firefox_driver(
self,
browser_options: BrowserOptions,
proxy_config: Optional[ProxyConfig] = None,
detection_evasion: Optional[DetectionEvasionConfig] = None
) -> WebDriver:
options = FirefoxOptions()
# Modo headless
if browser_options.headless:
options.add_argument("--headless")
# User agent
user_agent = browser_options.user_agent
if detection_evasion and detection_evasion.randomize_user_agent:
user_agent = random.choice(self.user_agents)
if user_agent:
options.set_preference("general.useragent.override", user_agent)
# Configuraciones de contenido
if browser_options.disable_images:
options.set_preference("permissions.default.image", 2)
if browser_options.disable_javascript:
options.set_preference("javascript.enabled", False)
# Configuraciones de privacidad
if browser_options.incognito:
options.add_argument("--private")
# Configuración de proxy
if proxy_config:
if proxy_config.http:
proxy_parts = proxy_config.http.replace("http://", "").split(":")
if len(proxy_parts) == 2:
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.http", proxy_parts[0])
options.set_preference("network.proxy.http_port", int(proxy_parts[1]))
options.set_preference("network.proxy.ssl", proxy_parts[0])
options.set_preference("network.proxy.ssl_port", int(proxy_parts[1]))
# Configurar servicio
service = FirefoxService(GeckoDriverManager().install())
# Crear driver
driver = webdriver.Firefox(service=service, options=options)
# Configurar tamaño de ventana
if not browser_options.headless:
width = browser_options.window_width
height = browser_options.window_height
if detection_evasion and detection_evasion.randomize_viewport:
width += random.randint(-100, 100)
height += random.randint(-50, 50)
driver.set_window_size(width, height)
return driver
def create_driver(
self,
browser_type: str,
browser_options: BrowserOptions,
proxy_config: Optional[ProxyConfig] = None,
detection_evasion: Optional[DetectionEvasionConfig] = None
) -> Dict[str, Any]:
browser_type = browser_type.lower()
if browser_type == "chrome":
driver = self.create_chrome_driver(browser_options, proxy_config, detection_evasion)
return {"driver": driver, "user_data_dir": getattr(driver, 'user_data_dir', None)}
elif browser_type == "firefox":
driver = self.create_firefox_driver(browser_options, proxy_config, detection_evasion)
return {"driver": driver, "user_data_dir": None}
else:
return user_data_dire ValueError(f"Tipo de navegador no soportado: {browser_type}")