Пишу регистратор почтовых ящиков Yahoo на Python. Использую selenium-wire для работы через SOCKS5-прокси с авторизацией. Проблема: браузер запускается, но страница регистрации Yahoo не грузится, после чего браузер закрывается.
Конфигурация:
Python 3.13, Windows 10
selenium-wire 5.1.0
undetected-chromedriver не используется (полностью перешёл на selenium-wire)
Chrome 125+
Прокси:
Формат: ip:port:login:pass
SOCKS5, с авторизацией
Прокси рабочие (проверял через curl и в обычном браузере)
Что уже перепробовал:
Менял несколько разных SOCKS5 прокси (с разных провайдеров) — результат тот же.
Добавлял disable_capture = True и verify_ssl = False.
Пробовал загружать about:blank перед переходом на Yahoo.
Вручную через браузер эти же прокси работают.
Страница не грузится, в логах ошибок от selenium-wire нет, браузер просто закрывается.
В чём может быть причина? Может, Yahoo блокирует запросы через selenium-wire, или нужны дополнительные аргументы для Chrome?
# core/browser.py
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import TimeoutException
import random
import time
import logging
logger = logging.getLogger(__name__)
class BrowserManager:
def __init__(self, headless=False, window_size=(1920, 1080), proxy=None):
self.headless = headless
self.window_size = window_size
self.proxy = proxy # строка в формате "ip:port:login:pass"
self.driver = None
self._parse_proxy()
def _parse_proxy(self):
"""Парсит прокси и подготавливает seleniumwire-options"""
self.seleniumwire_options = {}
if not self.proxy:
return
# Если прокси уже содержит 127.0.0.1:8081 (мост) — не трогаем
if self.proxy.startswith('127.0.0.1') or self.proxy.startswith('localhost'):
self.seleniumwire_options = {
'proxy': {
'http': f'http://{self.proxy}',
'https': f'http://{self.proxy}',
'no_proxy': 'localhost,127.0.0.1'
}
}
logger.info(f"✅ Используется локальный мост: {self.proxy}")
return
# Парсим SOCKS5 прокси (ip:port:login:pass)
parts = self.proxy.split(':')
if len(parts) >= 4:
ip, port, login, password = parts[0], parts[1], parts[2], parts[3]
self.seleniumwire_options = {
'proxy': {
'http': f'socks5://{login}:{password}@{ip}:{port}',
'https': f'socks5://{login}:{password}@{ip}:{port}',
'no_proxy': 'localhost,127.0.0.1'
}
}
logger.info(f"✅ Используется SOCKS5 прокси: {ip}:{port}")
else:
logger.warning(f"⚠️ Неизвестный формат прокси: {self.proxy}")
self.seleniumwire_options['verify_ssl'] = False
# Do not intercept/modify traffic; this avoids mitmproxy TLS failures.
self.seleniumwire_options['disable_capture'] = True
def start(self):
"""Запускает браузер через selenium-wire"""
chrome_options = Options()
# Базовые настройки
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-setuid-sandbox')
chrome_options.add_argument('--disable-web-security')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-extensions')
chrome_options.add_argument('--disable-popup-blocking')
chrome_options.add_argument('--disable-notifications')
# Headless
if self.headless:
chrome_options.add_argument('--headless=new')
# User-Agent
chrome_options.add_argument(
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
# Размер окна
chrome_options.add_argument(f'--window-size={self.window_size[0]},{self.window_size[1]}')
try:
self.driver = webdriver.Chrome(
options=chrome_options,
seleniumwire_options=self.seleniumwire_options
)
# Анти-детект
self.driver.execute_script("""
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
window.chrome = { runtime: {} };
""")
logger.info("✅ Браузер запущен (selenium-wire)")
return self.driver
except Exception as e:
logger.error(f"❌ Ошибка запуска браузера: {e}")
raise
def stop(self):
if self.driver:
try:
self.driver.quit()
logger.info("✅ Браузер закрыт")
except:
pass
def wait_for_element(self, by, selector, timeout=30):
try:
return WebDriverWait(self.driver, timeout).until(
EC.presence_of_element_located((by, selector))
)
except TimeoutException:
return None
def wait_for_clickable(self, by, selector, timeout=30):
try:
return WebDriverWait(self.driver, timeout).until(
EC.element_to_be_clickable((by, selector))
)
except TimeoutException:
return None
def human_type(self, element, text, delay_range=(50, 150)):
if not element:
return
element.click()
element.clear()
for char in text:
element.send_keys(char)
time.sleep(random.uniform(delay_range[0] / 1000, delay_range[1] / 1000))
time.sleep(random.uniform(0.2, 0.5))
def human_scroll(self, amount=None):
if not amount:
amount = random.randint(100, 500)
for _ in range(random.randint(2, 5)):
self.driver.execute_script(f"window.scrollBy(0, {random.randint(100, amount)});")
time.sleep(random.uniform(0.3, 1.0))
def random_mouse_move(self):
try:
actions = ActionChains(self.driver)
actions.move_by_offset(random.randint(100, 800), random.randint(100, 600))
actions.perform()
time.sleep(random.uniform(0.1, 0.3))
except:
pass
def get_cookies(self):
try:
cookies = self.driver.get_cookies()
return [{
'name': c['name'],
'value': c['value'],
'domain': c.get('domain', '.yahoo.com'),
'path': c.get('path', '/'),
'expires': c.get('expiry', None),
'httpOnly': c.get('httpOnly', False),
'secure': c.get('secure', False),
'sameSite': c.get('sameSite', 'None')
} for c in cookies]
except:
return []