• XSS.stack #1 – первый литературный журнал от юзеров форума

Как обойти фрод Twitch?

Velaro

floppy-диск
Пользователь
Регистрация
01.06.2025
Сообщения
6
Реакции
1
При авторизации вылазит фрод "Ваш браузер не поддерживается"

Screenshot_20250612_221712_com_hihonor_photos_SlotAlbumActivity.jpg

Я испробовал много чего.
Selenium, playwright, playwright, Undetected-Playwright, no-driver, Camoufox, zendriver и ничего из этого не помогло.

Единственное что обходит фрод: BAS, с использованием платных отпечатков, и библиотека: https://github.com/MiddleSchoolStudent/BotBrowser

BAS сразу мимо так как это костыли, BotBrowser проработал месяц, и начал выдавать фрод, автор говорит что проблема в версии браузера, я покупал 135 версию когда уже есть 137, и хочет чтобы я покупал каждые 2-3 месяца новые версии, по 500$ (либа платная).
Но даже если и покупать эту библиотеку, то у него есть проблема в использовании прокси, он выдаёт фрод каждые 5-12 авторизаций с использованием 1 папки User_data (данные куки, кэш и тд) нужно делать тысячи действий, а папок нужно на десятки ГБ, и со временем они заспамливаются и тоже уходят в фрод.

Если делать без прокси то тысячи авторизация проходят без единого фрода, с использованием 1 папки User data, но мне нужно использовать прокси для других действий в твиче.

В итоге я ищу библиотеку или варианты обхода на Python (в приоритете Playwright), который сможет обойти фрод Twitch (Защита Kasada) + с использованием прокси, если есть варианты то предлагайте что нибудь другое, желательно без оплаты за какое либо действие и без ежемесячной оплаты.
 
При авторизации вылазит фрод "Ваш браузер не поддерживается"

Посмотреть вложение 108291

Я испробовал много чего.
Selenium, playwright, playwright, Undetected-Playwright, no-driver, Camoufox, zendriver и ничего из этого не помогло.

Единственное что обходит фрод: BAS, с использованием платных отпечатков, и библиотека: https://github.com/MiddleSchoolStudent/BotBrowser

BAS сразу мимо так как это костыли, BotBrowser проработал месяц, и начал выдавать фрод, автор говорит что проблема в версии браузера, я покупал 135 версию когда уже есть 137, и хочет чтобы я покупал каждые 2-3 месяца новые версии, по 500$ (либа платная).
Но даже если и покупать эту библиотеку, то у него есть проблема в использовании прокси, он выдаёт фрод каждые 5-12 авторизаций с использованием 1 папки User_data (данные куки, кэш и тд) нужно делать тысячи действий, а папок нужно на десятки ГБ, и со временем они заспамливаются и тоже уходят в фрод.

Если делать без прокси то тысячи авторизация проходят без единого фрода, с использованием 1 папки User data, но мне нужно использовать прокси для других действий в твиче.

В итоге я ищу библиотеку или варианты обхода на Python (в приоритете Playwright), который сможет обойти фрод Twitch (Защита Kasada) + с использованием прокси, если есть варианты то предлагайте что нибудь другое, желательно без оплаты за какое либо действие и без ежемесячной оплаты.
я ровно эту же проблему решил 5 лет назад когда писал авторегер, но уже все забыл, попробуй просто подставлять юзер агент самого самого последнего гуглхрома
 
я ровно эту же проблему решил 5 лет назад когда писал авторегер, но уже все забыл, попробуй просто подставлять юзер агент самого самого последнего гуглхрома
Буквально сегодня это и пробовал, использовал профили Bot Browser 135 версии, и юзер агенты 137 версии (проверил в браузере, показывало 137 версию) и это не помогло.
 
я ровно эту же проблему решил 5 лет назад когда писал авторегер, но уже все забыл, попробуй просто подставлять юзер агент самого самого последнего гуглхрома
Касада не банит старый хром...

Буквально сегодня это и пробовал, использовал профили Bot Browser 135 версии, и юзер агенты 137 версии (проверил в браузере, показывало 137 версию) и это не помогло.
Сударь, вам детектит CDP Runtime/CDP Input Event. Решение - https://t.me/offshorebotnet/309 (На касаде не тестил, но должно работать)
 
При авторизации вылазит фрод "Ваш браузер не поддерживается"

Посмотреть вложение 108291

Я испробовал много чего.
Selenium, playwright, playwright, Undetected-Playwright, no-driver, Camoufox, zendriver и ничего из этого не помогло.

Единственное что обходит фрод: BAS, с использованием платных отпечатков, и библиотека: https://github.com/MiddleSchoolStudent/BotBrowser

BAS сразу мимо так как это костыли, BotBrowser проработал месяц, и начал выдавать фрод, автор говорит что проблема в версии браузера, я покупал 135 версию когда уже есть 137, и хочет чтобы я покупал каждые 2-3 месяца новые версии, по 500$ (либа платная).
Но даже если и покупать эту библиотеку, то у него есть проблема в использовании прокси, он выдаёт фрод каждые 5-12 авторизаций с использованием 1 папки User_data (данные куки, кэш и тд) нужно делать тысячи действий, а папок нужно на десятки ГБ, и со временем они заспамливаются и тоже уходят в фрод.

Если делать без прокси то тысячи авторизация проходят без единого фрода, с использованием 1 папки User data, но мне нужно использовать прокси для других действий в твиче.

В итоге я ищу библиотеку или варианты обхода на Python (в приоритете Playwright), который сможет обойти фрод Twitch (Защита Kasada) + с использованием прокси, если есть варианты то предлагайте что нибудь другое, желательно без оплаты за какое либо действие и без ежемесячной оплаты.
через антик тоже не пускает? дольфин предоставляет бесплатное апи
 
через антик тоже не пускает? дольфин предоставляет бесплатное апи
Попробовал AdsPower, с использованием апи не пускает, всегда фрод. Если делать без апи, все в ручную. То работает без проблем
 
Попробовал AdsPower, с использованием апи не пускает, всегда фрод. Если делать без апи, все в ручную. То работает без проблем
ты автоматизацию только на хромиум пробовал, или на гекко тоже?
 
Попробуйте Playwright или Selenium пропустить через хорошие прокси.

Вот пример кода на Антидетект драйвере хрониума у селениума (код уже не рабочий):
Python:
import time
import json
import random
import re
from selenium import webdriver
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.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
from datetime import datetime
import undetected_chromedriver as uc


class FonbetTennisParser:
    def __init__(self, headless=False, use_undetected=True):
        """
        Инициализация парсера
        :param headless: True для работы без GUI браузера (не рекомендуется для обхода защиты)
        :param use_undetected: Использовать undetected-chromedriver
        """
        self.url = "https://fon.bet/live/tennis"
        self.driver = None
        self.headless = headless
        self.use_undetected = use_undetected
     
    def setup_driver(self):
        """Настройка и запуск веб-драйвера с максимальной маскировкой"""
     
        if self.use_undetected:
            # Используем undetected-chromedriver
            print("Используем undetected-chromedriver...")
            options = uc.ChromeOptions()
         
            # Базовые настройки
            options.add_argument('--no-sandbox')
            options.add_argument('--disable-dev-shm-usage')
            options.add_argument('--disable-gpu')
            options.add_argument('--window-size=1920,1080')
            options.add_argument('--start-maximized')
         
            # Отключаем автоматизацию
            options.add_argument("--disable-blink-features=AutomationControlled")
         
            # Важно: НЕ используем headless режим для обхода защиты
            if self.headless:
                print("ВНИМАНИЕ: Headless режим может быть обнаружен защитой!")
             
            # Создаем драйвер
            self.driver = uc.Chrome(options=options, version_main=None)
         
        else:
            # Стандартный ChromeDriver с максимальными настройками
            chrome_options = Options()
         
            # Отключаем все признаки автоматизации
            chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
            chrome_options.add_experimental_option('useAutomationExtension', False)
            chrome_options.add_argument("--disable-blink-features=AutomationControlled")
         
            # Настройки профиля
            chrome_options.add_argument('--no-sandbox')
            chrome_options.add_argument('--disable-dev-shm-usage')
            chrome_options.add_argument('--disable-gpu')
            chrome_options.add_argument('--window-size=1920,1080')
            chrome_options.add_argument('--start-maximized')
         
            # Добавляем случайный user-agent
            user_agents = [
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
                '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 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
                'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
            ]
            chrome_options.add_argument(f'user-agent={random.choice(user_agents)}')
         
            # Настройки для имитации реального браузера
            prefs = {
                'credentials_enable_service': False,
                'profile.password_manager_enabled': False,
                'profile.default_content_setting_values.notifications': 2,
                'excludeSwitches': ['enable-automation'],
                'useAutomationExtension': False,
            }
            chrome_options.add_experimental_option('prefs', prefs)
         
            # Добавляем расширения браузера (имитация)
            chrome_options.add_argument('--disable-plugins-discovery')
            chrome_options.add_argument('--disable-extensions')
         
            if self.headless:
                chrome_options.add_argument('--headless=new')
             
            self.driver = webdriver.Chrome(options=chrome_options)
         
            # Выполняем JavaScript для маскировки
            self.apply_stealth_scripts()
         
    def apply_stealth_scripts(self):
        """Применение JavaScript скриптов для маскировки автоматизации"""
     
        # Скрываем webdriver
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'webdriver', {
                    get: () => undefined
                });
            '''
        })
     
        # Скрываем Chrome automation
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                window.chrome = {
                    runtime: {},
                };
            '''
        })
     
        # Добавляем правильные permissions
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'permissions', {
                    get: () => {
                        return {
                            query: () => Promise.resolve({ state: 'granted' })
                        }
                    }
                });
            '''
        })
     
        # Маскируем plugins
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'plugins', {
                    get: () => [
                        {
                            0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
                            description: "Portable Document Format",
                            filename: "internal-pdf-viewer",
                            length: 1,
                            name: "Chrome PDF Plugin"
                        }
                    ]
                });
            '''
        })
     
        # Правильный языки
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'languages', {
                    get: () => ['ru-RU', 'ru', 'en-US', 'en']
                });
            '''
        })
     
        # WebGL Vendor
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                const getParameter = WebGLRenderingContext.prototype.getParameter;
                WebGLRenderingContext.prototype.getParameter = function(parameter) {
                    if (parameter === 37445) {
                        return 'Intel Inc.';
                    }
                    if (parameter === 37446) {
                        return 'Intel Iris OpenGL Engine';
                    }
                    return getParameter(parameter);
                };
            '''
        })
     
    def human_like_mouse_move(self, element):
        """Человекоподобное движение мыши"""
        action = ActionChains(self.driver)
     
        # Получаем текущую позицию мыши
        action.move_to_element_with_offset(element, 0, 0)
     
        # Делаем несколько промежуточных движений
        for i in range(random.randint(2, 4)):
            x_offset = random.randint(-50, 50)
            y_offset = random.randint(-50, 50)
            action.move_by_offset(x_offset, y_offset)
            action.pause(random.uniform(0.1, 0.3))
         
        # Наводим на элемент
        action.move_to_element(element)
        action.pause(random.uniform(0.2, 0.5))
        action.perform()
     
    def random_delay(self, min_delay=0.5, max_delay=2.0):
        """Случайная задержка для имитации человека"""
        time.sleep(random.uniform(min_delay, max_delay))
     
    def parse_tennis_matches(self):
        """Основной метод парсинга с обходом защиты"""
        try:
            self.setup_driver()
         
            print(f"Загрузка страницы: {self.url}")
            print("Имитируем поведение человека...")
         
            # Сначала заходим на главную страницу
            print("Заходим на главную страницу...")
            self.driver.get("https://fon.bet")
            self.random_delay(2, 4)
         
            # Делаем несколько случайных движений мышью
            print("Имитируем активность пользователя...")
            body = self.driver.find_element(By.TAG_NAME, "body")
            for _ in range(3):
                x = random.randint(100, 800)
                y = random.randint(100, 600)
                ActionChains(self.driver).move_to_element_with_offset(body, x, y).perform()
                self.random_delay(0.3, 0.7)
         
            # Теперь переходим на страницу с теннисом
            print("Переходим на страницу live тенниса...")
            self.driver.get(self.url)
            self.random_delay(3, 5)
         
            # Проверяем, не попали ли мы на страницу с предупреждением
            page_text = self.driver.find_element(By.TAG_NAME, 'body').text.lower()
            if any(word in page_text for word in ['подозрен', 'suspicious', 'проверка', 'captcha', 'verify']):
                print("ВНИМАНИЕ: Обнаружена страница проверки!")
                print("Возможные решения:")
                print("1. Используйте use_undetected=True")
                print("2. Запустите без headless режима")
                print("3. Попробуйте использовать прокси")
                print("4. Добавьте больше задержек между действиями")
             
                # Сохраняем скриншот
                self.driver.save_screenshot("verification_page.png")
                print("Скриншот сохранен: verification_page.png")
                return []
         
            # Прокручиваем страницу как человек
            print("Прокручиваем страницу...")
            for _ in range(3):
                scroll_height = random.randint(300, 700)
                self.driver.execute_script(f"window.scrollBy(0, {scroll_height});")
                self.random_delay(0.5, 1.5)
         
            # Прокручиваем обратно вверх
            self.driver.execute_script("window.scrollTo(0, 0);")
            self.random_delay(1, 2)
         
            # Теперь начинаем парсинг
            print("Начинаем поиск матчей...")
            matches = self.parse_matches_safe()
         
            return matches
         
        except Exception as e:
            print(f"Ошибка: {str(e)}")
            import traceback
            traceback.print_exc()
            return []
        finally:
            if self.driver:
                self.random_delay(2, 3)  # Задержка перед закрытием
                self.driver.quit()
             
    def parse_matches_safe(self):
        """Безопасный парсинг матчей"""
        matches_data = []
     
        # Ждем загрузку контента
        self.random_delay(2, 3)
     
        # Список возможных селекторов для Fonbet
        selectors = [
            # Основные селекторы для событий
            "div[class*='event-view']",
            "a[class*='table__row']",
            "div[class*='table__row']",
            "div[class*='sport-section__row']",
            "div[class*='SportSection__row']",
            "div[class*='event-row']",
            "div[class*='EventRow']",
            "div[class*='live-event']",
            "div[class*='LiveEvent']",
            # Специфичные для тенниса
            "[data-sport='tennis']",
            "[data-sport-id='2']",
            "div[class*='tennis']",
        ]
     
        found = False
        for selector in selectors:
            try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                if elements:
                    print(f"Найдено {len(elements)} элементов с селектором: {selector}")
                 
                    for elem in elements[:10]:  # Парсим первые 10 матчей
                        try:
                            match_data = self.extract_match_data(elem)
                            if match_data and match_data.get('team1'):
                                matches_data.append(match_data)
                                found = True
                        except:
                            continue
                         
                    if found:
                        break
                     
            except:
                continue
             
        # Если ничего не нашли, сохраняем отладочную информацию
        if not matches_data:
            self.save_debug_info()
         
        return matches_data
     
    def extract_match_data(self, element):
        """Извлечение данных матча"""
        match_data = {}
     
        try:
            # Получаем весь текст
            text = element.text
            lines = [line.strip() for line in text.split('\n') if line.strip()]
         
            # Ищем игроков (обычно самые длинные строки без цифр)
            player_lines = []
            for line in lines:
                if len(line) > 3 and not re.match(r'^\d+[\.:]\d+', line) and not re.match(r'^\d+\.\d{2}$', line):
                    player_lines.append(line)
                 
            if len(player_lines) >= 2:
                match_data['team1'] = player_lines[0]
                match_data['team2'] = player_lines[1]
             
            # Ищем счет
            score_pattern = r'(\d+)\s*[:]\s*(\d+)'
            for line in lines:
                score_match = re.search(score_pattern, line)
                if score_match:
                    match_data['score'] = f"{score_match.group(1)}:{score_match.group(2)}"
                    break
                 
            # Ищем коэффициенты
            odds = []
            for line in lines:
                if re.match(r'^\d+\.\d{2}$', line):
                    odds.append(line)
            if odds:
                match_data['odds'] = odds
             
            # Время/статус матча
            for line in lines:
                if any(word in line.lower() for word in ['set', 'game', 'тайм', 'период']):
                    match_data['status'] = line
                    break
                 
        except Exception as e:
            print(f"Ошибка извлечения данных: {e}")
         
        return match_data
     
    def save_debug_info(self):
        """Сохранение отладочной информации"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
     
        # HTML
        with open(f'fonbet_debug_{timestamp}.html', 'w', encoding='utf-8') as f:
            f.write(self.driver.page_source)
         
        # Скриншот
        self.driver.save_screenshot(f'fonbet_debug_{timestamp}.png')
     
        print(f"\nОтладочная информация сохранена:")
        print(f"- fonbet_debug_{timestamp}.html")
        print(f"- fonbet_debug_{timestamp}.png")
     
    def save_to_json(self, data, filename='tennis_matches.json'):
        """Сохранение данных в JSON"""
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        print(f"Данные сохранены в {filename}")
     
    def print_matches(self, matches):
        """Вывод информации о матчах"""
        if not matches:
            print("\nМатчи не найдены!")
            return
         
        print(f"\n{'='*80}")
        print(f"Найдено матчей: {len(matches)}")
        print(f"{'='*80}\n")
     
        for i, match in enumerate(matches, 1):
            print(f"Матч #{i}")
            print(f"{match.get('team1', 'N/A')} vs {match.get('team2', 'N/A')}")
            if match.get('score'):
                print(f"Счет: {match['score']}")
            if match.get('status'):
                print(f"Статус: {match['status']}")
            if match.get('odds'):
                print(f"Коэффициенты: {', '.join(match['odds'])}")
            print(f"{'-'*80}\n")


def main():
    """
    Основная функция запуска парсера
 
    ВАЖНО: Для обхода защиты от ботов:
    1. Установите: pip install undetected-chromedriver
    2. Используйте use_undetected=True
    3. НЕ используйте headless режим
    4. Запускайте с задержками между запусками
    """
 
    print("="*80)
    print("Fonbet Tennis Parser с обходом защиты")
    print("="*80)
    print("\nДля работы необходимо:")
    print("1. pip install selenium")
    print("2. pip install undetected-chromedriver")
    print("3. Актуальный ChromeDriver\n")
 
    # Создаем парсер с защитой от обнаружения
    parser = FonbetTennisParser(
        headless=False,  # НЕ используем headless для обхода защиты
        use_undetected=True  # Используем undetected-chromedriver
    )
 
    # Запускаем парсинг
    matches = parser.parse_tennis_matches()
 
    # Выводим результаты
    parser.print_matches(matches)
 
    # Сохраняем данные
    if matches:
        parser.save_to_json(matches)
     
    return matches


# Дополнительный класс для работы без undetected-chromedriver
class SimpleFonbetParser(FonbetTennisParser):
    """Упрощенная версия без undetected-chromedriver"""
 
    def __init__(self):
        super().__init__(headless=False, use_undetected=False)
        print("Используется упрощенная версия парсера")
        print("Если попадаете на страницу проверки, установите undetected-chromedriver")


if __name__ == "__main__":
    try:
        # Пробуем с undetected-chromedriver
        results = main()
    except ImportError:
        print("\nundetected-chromedriver не установлен!")
        print("Установите: pip install undetected-chromedriver")
        print("\nЗапускаем упрощенную версию...\n")
     
        # Запускаем упрощенную версию
        simple_parser = SimpleFonbetParser()
        results = simple_parser.parse_tennis_matches()
        simple_parser.print_matches(results)
А с каких пор форум стал филлиалом ChatGPT?

Антидетект
1749990904158.png

поржал, спасибо
 
А с каких пор форум стал филлиалом ChatGPT?
Какая разница? Филиал кожаных мешков тоже бывает так себе, этот код отрабатывал в свое время и парсил нужную инфу. Покажите свой рабочий вариант, поржем вместе.
 
Какая разница? Филиал кожаных мешков тоже бывает так себе, этот код отрабатывал в свое время и парсил нужную инфу. Покажите свой рабочий вариант, поржем вместе.
Причем тут мой вариант? Этот код не обойдет даже защиту школьника на коленке из ддос комьюнити, не говоря уже о касаде. Вы советуете человеку совершить суицид
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Попробуйте Playwright или Selenium пропустить через хорошие прокси.

Вот пример кода на Антидетект драйвере хрониума у селениума (код уже не рабочий):
Python:
import time
import json
import random
import re
from selenium import webdriver
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.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
from datetime import datetime
import undetected_chromedriver as uc


class FonbetTennisParser:
    def __init__(self, headless=False, use_undetected=True):
        """
        Инициализация парсера
        :param headless: True для работы без GUI браузера (не рекомендуется для обхода защиты)
        :param use_undetected: Использовать undetected-chromedriver
        """
        self.url = "https://fon.bet/live/tennis"
        self.driver = None
        self.headless = headless
        self.use_undetected = use_undetected
     
    def setup_driver(self):
        """Настройка и запуск веб-драйвера с максимальной маскировкой"""
     
        if self.use_undetected:
            # Используем undetected-chromedriver
            print("Используем undetected-chromedriver...")
            options = uc.ChromeOptions()
         
            # Базовые настройки
            options.add_argument('--no-sandbox')
            options.add_argument('--disable-dev-shm-usage')
            options.add_argument('--disable-gpu')
            options.add_argument('--window-size=1920,1080')
            options.add_argument('--start-maximized')
         
            # Отключаем автоматизацию
            options.add_argument("--disable-blink-features=AutomationControlled")
         
            # Важно: НЕ используем headless режим для обхода защиты
            if self.headless:
                print("ВНИМАНИЕ: Headless режим может быть обнаружен защитой!")
             
            # Создаем драйвер
            self.driver = uc.Chrome(options=options, version_main=None)
         
        else:
            # Стандартный ChromeDriver с максимальными настройками
            chrome_options = Options()
         
            # Отключаем все признаки автоматизации
            chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
            chrome_options.add_experimental_option('useAutomationExtension', False)
            chrome_options.add_argument("--disable-blink-features=AutomationControlled")
         
            # Настройки профиля
            chrome_options.add_argument('--no-sandbox')
            chrome_options.add_argument('--disable-dev-shm-usage')
            chrome_options.add_argument('--disable-gpu')
            chrome_options.add_argument('--window-size=1920,1080')
            chrome_options.add_argument('--start-maximized')
         
            # Добавляем случайный user-agent
            user_agents = [
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
                '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 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
                'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
            ]
            chrome_options.add_argument(f'user-agent={random.choice(user_agents)}')
         
            # Настройки для имитации реального браузера
            prefs = {
                'credentials_enable_service': False,
                'profile.password_manager_enabled': False,
                'profile.default_content_setting_values.notifications': 2,
                'excludeSwitches': ['enable-automation'],
                'useAutomationExtension': False,
            }
            chrome_options.add_experimental_option('prefs', prefs)
         
            # Добавляем расширения браузера (имитация)
            chrome_options.add_argument('--disable-plugins-discovery')
            chrome_options.add_argument('--disable-extensions')
         
            if self.headless:
                chrome_options.add_argument('--headless=new')
             
            self.driver = webdriver.Chrome(options=chrome_options)
         
            # Выполняем JavaScript для маскировки
            self.apply_stealth_scripts()
         
    def apply_stealth_scripts(self):
        """Применение JavaScript скриптов для маскировки автоматизации"""
     
        # Скрываем webdriver
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'webdriver', {
                    get: () => undefined
                });
            '''
        })
     
        # Скрываем Chrome automation
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                window.chrome = {
                    runtime: {},
                };
            '''
        })
     
        # Добавляем правильные permissions
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'permissions', {
                    get: () => {
                        return {
                            query: () => Promise.resolve({ state: 'granted' })
                        }
                    }
                });
            '''
        })
     
        # Маскируем plugins
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'plugins', {
                    get: () => [
                        {
                            0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
                            description: "Portable Document Format",
                            filename: "internal-pdf-viewer",
                            length: 1,
                            name: "Chrome PDF Plugin"
                        }
                    ]
                });
            '''
        })
     
        # Правильный языки
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                Object.defineProperty(navigator, 'languages', {
                    get: () => ['ru-RU', 'ru', 'en-US', 'en']
                });
            '''
        })
     
        # WebGL Vendor
        self.driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
            'source': '''
                const getParameter = WebGLRenderingContext.prototype.getParameter;
                WebGLRenderingContext.prototype.getParameter = function(parameter) {
                    if (parameter === 37445) {
                        return 'Intel Inc.';
                    }
                    if (parameter === 37446) {
                        return 'Intel Iris OpenGL Engine';
                    }
                    return getParameter(parameter);
                };
            '''
        })
     
    def human_like_mouse_move(self, element):
        """Человекоподобное движение мыши"""
        action = ActionChains(self.driver)
     
        # Получаем текущую позицию мыши
        action.move_to_element_with_offset(element, 0, 0)
     
        # Делаем несколько промежуточных движений
        for i in range(random.randint(2, 4)):
            x_offset = random.randint(-50, 50)
            y_offset = random.randint(-50, 50)
            action.move_by_offset(x_offset, y_offset)
            action.pause(random.uniform(0.1, 0.3))
         
        # Наводим на элемент
        action.move_to_element(element)
        action.pause(random.uniform(0.2, 0.5))
        action.perform()
     
    def random_delay(self, min_delay=0.5, max_delay=2.0):
        """Случайная задержка для имитации человека"""
        time.sleep(random.uniform(min_delay, max_delay))
     
    def parse_tennis_matches(self):
        """Основной метод парсинга с обходом защиты"""
        try:
            self.setup_driver()
         
            print(f"Загрузка страницы: {self.url}")
            print("Имитируем поведение человека...")
         
            # Сначала заходим на главную страницу
            print("Заходим на главную страницу...")
            self.driver.get("https://fon.bet")
            self.random_delay(2, 4)
         
            # Делаем несколько случайных движений мышью
            print("Имитируем активность пользователя...")
            body = self.driver.find_element(By.TAG_NAME, "body")
            for _ in range(3):
                x = random.randint(100, 800)
                y = random.randint(100, 600)
                ActionChains(self.driver).move_to_element_with_offset(body, x, y).perform()
                self.random_delay(0.3, 0.7)
         
            # Теперь переходим на страницу с теннисом
            print("Переходим на страницу live тенниса...")
            self.driver.get(self.url)
            self.random_delay(3, 5)
         
            # Проверяем, не попали ли мы на страницу с предупреждением
            page_text = self.driver.find_element(By.TAG_NAME, 'body').text.lower()
            if any(word in page_text for word in ['подозрен', 'suspicious', 'проверка', 'captcha', 'verify']):
                print("ВНИМАНИЕ: Обнаружена страница проверки!")
                print("Возможные решения:")
                print("1. Используйте use_undetected=True")
                print("2. Запустите без headless режима")
                print("3. Попробуйте использовать прокси")
                print("4. Добавьте больше задержек между действиями")
             
                # Сохраняем скриншот
                self.driver.save_screenshot("verification_page.png")
                print("Скриншот сохранен: verification_page.png")
                return []
         
            # Прокручиваем страницу как человек
            print("Прокручиваем страницу...")
            for _ in range(3):
                scroll_height = random.randint(300, 700)
                self.driver.execute_script(f"window.scrollBy(0, {scroll_height});")
                self.random_delay(0.5, 1.5)
         
            # Прокручиваем обратно вверх
            self.driver.execute_script("window.scrollTo(0, 0);")
            self.random_delay(1, 2)
         
            # Теперь начинаем парсинг
            print("Начинаем поиск матчей...")
            matches = self.parse_matches_safe()
         
            return matches
         
        except Exception as e:
            print(f"Ошибка: {str(e)}")
            import traceback
            traceback.print_exc()
            return []
        finally:
            if self.driver:
                self.random_delay(2, 3)  # Задержка перед закрытием
                self.driver.quit()
             
    def parse_matches_safe(self):
        """Безопасный парсинг матчей"""
        matches_data = []
     
        # Ждем загрузку контента
        self.random_delay(2, 3)
     
        # Список возможных селекторов для Fonbet
        selectors = [
            # Основные селекторы для событий
            "div[class*='event-view']",
            "a[class*='table__row']",
            "div[class*='table__row']",
            "div[class*='sport-section__row']",
            "div[class*='SportSection__row']",
            "div[class*='event-row']",
            "div[class*='EventRow']",
            "div[class*='live-event']",
            "div[class*='LiveEvent']",
            # Специфичные для тенниса
            "[data-sport='tennis']",
            "[data-sport-id='2']",
            "div[class*='tennis']",
        ]
     
        found = False
        for selector in selectors:
            try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                if elements:
                    print(f"Найдено {len(elements)} элементов с селектором: {selector}")
                 
                    for elem in elements[:10]:  # Парсим первые 10 матчей
                        try:
                            match_data = self.extract_match_data(elem)
                            if match_data and match_data.get('team1'):
                                matches_data.append(match_data)
                                found = True
                        except:
                            continue
                         
                    if found:
                        break
                     
            except:
                continue
             
        # Если ничего не нашли, сохраняем отладочную информацию
        if not matches_data:
            self.save_debug_info()
         
        return matches_data
     
    def extract_match_data(self, element):
        """Извлечение данных матча"""
        match_data = {}
     
        try:
            # Получаем весь текст
            text = element.text
            lines = [line.strip() for line in text.split('\n') if line.strip()]
         
            # Ищем игроков (обычно самые длинные строки без цифр)
            player_lines = []
            for line in lines:
                if len(line) > 3 and not re.match(r'^\d+[\.:]\d+', line) and not re.match(r'^\d+\.\d{2}$', line):
                    player_lines.append(line)
                 
            if len(player_lines) >= 2:
                match_data['team1'] = player_lines[0]
                match_data['team2'] = player_lines[1]
             
            # Ищем счет
            score_pattern = r'(\d+)\s*[:]\s*(\d+)'
            for line in lines:
                score_match = re.search(score_pattern, line)
                if score_match:
                    match_data['score'] = f"{score_match.group(1)}:{score_match.group(2)}"
                    break
                 
            # Ищем коэффициенты
            odds = []
            for line in lines:
                if re.match(r'^\d+\.\d{2}$', line):
                    odds.append(line)
            if odds:
                match_data['odds'] = odds
             
            # Время/статус матча
            for line in lines:
                if any(word in line.lower() for word in ['set', 'game', 'тайм', 'период']):
                    match_data['status'] = line
                    break
                 
        except Exception as e:
            print(f"Ошибка извлечения данных: {e}")
         
        return match_data
     
    def save_debug_info(self):
        """Сохранение отладочной информации"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
     
        # HTML
        with open(f'fonbet_debug_{timestamp}.html', 'w', encoding='utf-8') as f:
            f.write(self.driver.page_source)
         
        # Скриншот
        self.driver.save_screenshot(f'fonbet_debug_{timestamp}.png')
     
        print(f"\nОтладочная информация сохранена:")
        print(f"- fonbet_debug_{timestamp}.html")
        print(f"- fonbet_debug_{timestamp}.png")
     
    def save_to_json(self, data, filename='tennis_matches.json'):
        """Сохранение данных в JSON"""
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        print(f"Данные сохранены в {filename}")
     
    def print_matches(self, matches):
        """Вывод информации о матчах"""
        if not matches:
            print("\nМатчи не найдены!")
            return
         
        print(f"\n{'='*80}")
        print(f"Найдено матчей: {len(matches)}")
        print(f"{'='*80}\n")
     
        for i, match in enumerate(matches, 1):
            print(f"Матч #{i}")
            print(f"{match.get('team1', 'N/A')} vs {match.get('team2', 'N/A')}")
            if match.get('score'):
                print(f"Счет: {match['score']}")
            if match.get('status'):
                print(f"Статус: {match['status']}")
            if match.get('odds'):
                print(f"Коэффициенты: {', '.join(match['odds'])}")
            print(f"{'-'*80}\n")


def main():
    """
    Основная функция запуска парсера
 
    ВАЖНО: Для обхода защиты от ботов:
    1. Установите: pip install undetected-chromedriver
    2. Используйте use_undetected=True
    3. НЕ используйте headless режим
    4. Запускайте с задержками между запусками
    """
 
    print("="*80)
    print("Fonbet Tennis Parser с обходом защиты")
    print("="*80)
    print("\nДля работы необходимо:")
    print("1. pip install selenium")
    print("2. pip install undetected-chromedriver")
    print("3. Актуальный ChromeDriver\n")
 
    # Создаем парсер с защитой от обнаружения
    parser = FonbetTennisParser(
        headless=False,  # НЕ используем headless для обхода защиты
        use_undetected=True  # Используем undetected-chromedriver
    )
 
    # Запускаем парсинг
    matches = parser.parse_tennis_matches()
 
    # Выводим результаты
    parser.print_matches(matches)
 
    # Сохраняем данные
    if matches:
        parser.save_to_json(matches)
     
    return matches


# Дополнительный класс для работы без undetected-chromedriver
class SimpleFonbetParser(FonbetTennisParser):
    """Упрощенная версия без undetected-chromedriver"""
 
    def __init__(self):
        super().__init__(headless=False, use_undetected=False)
        print("Используется упрощенная версия парсера")
        print("Если попадаете на страницу проверки, установите undetected-chromedriver")


if __name__ == "__main__":
    try:
        # Пробуем с undetected-chromedriver
        results = main()
    except ImportError:
        print("\nundetected-chromedriver не установлен!")
        print("Установите: pip install undetected-chromedriver")
        print("\nЗапускаем упрощенную версию...\n")
     
        # Запускаем упрощенную версию
        simple_parser = SimpleFonbetParser()
        results = simple_parser.parse_tennis_matches()
        simple_parser.print_matches(results)
Уже вижу - Ты — опытный Python-разработчик и эксперт в автоматизации браузеров. Твоя задача — написать модуль для парсинга текущих матчей тенниса на сайте Fon.bet (раздел Live). Требования:
 
Причем тут мой вариант? Этот код не обойдет даже защиту школьника на коленке из ддос комьюнити, не говоря уже о касаде. Вы советуете человеку совершить суицид
Я же не предлагал этот код использовать полностью. Возможно какие-то фишки могли пригодиться оттуда.

P.S. В общем признаю, обкакали меня по делу, я ламерок. =(
 
Последнее редактирование:
Касада не банит старый хром...
Троеточие в конце выглядит пассивно-агрессивно. Не помню как конкретно обошел, помню только что неделю возился в БАСе, а решение оказалось очень простым и на поверхности
 
Решил проблему использованием антика по api, но и он не справлялся на все 100%, спустя пару авторизаций браузер уходил в блок и всегда выдавал фрод, пришлось сидеть 2 недели и настраивать все параметры. Теперь 50.000+ авторизаций проходят с 2-3% фродом.
 
Решил проблему использованием антика по api, но и он не справлялся на все 100%, спустя пару авторизаций браузер уходил в блок и всегда выдавал фрод, пришлось сидеть 2 недели и настраивать все параметры. Теперь 50.000+ авторизаций проходят с 2-3% фродом.
Подскажи, ключевую роль играет апи антика?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
через антик тоже не пускает? дольфин предоставляет бесплатное апи
уже нет вроде
 
1) Свежий хром
2) Реальный профиль с нагулянными рекламными куками.
3) Хороший айпи
4) Забудьте про headless версии, они выдают неправильный webgl слепок.
5) Переопределить некоторые свойства, которые выдают что был запуск под отладкой(CDP). (Можно нагуглить)
6) Изучать защитные системы, повесь хуки на все вызовы и обращения к свойствам(ES 6 Proxy) еще до загрузки страницы и смотри что защита дергает.
Рецепт, который работал для меня, но под чуть другие цели
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх