Скрипт, по открытию сайта и нажатия на нужный цвет(капча)

Рейтинг: 0Ответов: 1Опубликовано: 24.03.2023

нужен скрипт, который будет выполнять запрос на определенный сайт, там есть 6 цветов (красный, желтый, синий, серый, черный и зеленый) Как только он находит нужный цвет(Они могут быть разные), тоесть выглядит так же скриншот думаю все понятно, вот код, который я сделал, но я не думаю, что он работает, в чем проблема? так же хочу представить скрин с html кодом скрин2

from selenium.webdriver import Chrome, ChromeOptions
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from PIL import Image
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import io
import os 
vpn_extension_path = 'C:/Users/******/AppData/Local/Google/Chrome/User Data/Default/Extensions/hipncndjamdcmphkgngojegjblibadbe/1.11.7_0'
#Тут тебе нужно будет указать путь до расширения впн, я уже все так то сделал, главное установи https://chrome.google.com/webstore/detail/free-vpn-proxy-and-ad-blo/hipncndjamdcmphkgngojegjblibadbe?hl=ru
#И замени на себя в USERS
chrome_options = ChromeOptions()
options = Options()
chrome_options.add_argument('--load-extension={}'.format(vpn_extension_path))
options.add_argument('--ignore-certificate-errors')

chromedriver = ChromeService(ChromeDriverManager().install())
driver = Chrome(service=chromedriver, options=chrome_options)
driver.get("https://rutor.live") #Адрес сайта
 #ИСПОЛЬЗОВАТЬ С ВПН
screenshot = driver.get_screenshot_as_png()
screenshot = Image.open(io.BytesIO(screenshot))

width = driver.execute_script("return document.documentElement.scrollWidth")
height = driver.execute_script("return document.documentElement.scrollHeight")

for x in range(screenshot.size[0]):
    for y in range(screenshot.size[1]):
        pixel = screenshot.getpixel((x, y))
        pixel_color = tuple(list(pixel)[:3][::-1])
        if pixel_color in [(0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (128, 128, 128), (34, 143, 92)]:
            actions = ActionChains(driver)
            actions.move_to_element_with_offset(driver.find_element(By.XPATH, "//*[@id='content']/div"), x, y)
            actions.click()
            actions.perform()

Ответы

▲ 1

Тут будет общее решение, т.к. не хотелось возиться с selenium, плагинами и proxy/vpn.

А для проверки алгоритма сохранил страницу сайт с капчей в файл:

введите сюда описание изображения

Сайт показывает блоки с однородными цветами внутри элементе <div id="content", причем нужный цвет находится в <div>, в вариации в <em>. Сам же цвет описан как картинка в base64, что находится в атрибуте style в поле background-image.

Значит, действия:

  1. Вытащить элемент с нужным цветом. Для поиска использую CSS-селекторы
  2. Вытащить элементы с вариантами цвета
  3. Получить картинки элементов. Тут я использую вариант через background-image
  4. Найти нужный цвет

Для вытаскивания буду использовать BeautifulSoup - тут нет особой разницы, через что - главное получить элементы и значение атрибута style.

Функции:

  • get_rgb - извлекает цвет картинки из background-image. Тут используется регулярка
  • pixel_matches_color - функция для сравнения двух RGB, нагуглил тут. Значение параметра tolerance нужно подобрать - это разница между значением RGB. Как будет видно ниже, хоть на глаз цвет похож, есть разница: у меня нужный синий цвет был (1, 9, 254), а среди вариантов (0, 0, 255). Тут я tolerance взял с запасом

Код:

import re

from base64 import b64decode
from io import BytesIO

from bs4 import BeautifulSoup
from PIL import Image


PATTERN_BACKGROUND_IMAGE = re.compile('background-image: url\(data:image/\w+;base64,(.+)\)')


def get_rgb(style: str) -> tuple[int, int, int]:
    m = PATTERN_BACKGROUND_IMAGE.search(style)
    if not m:
        raise Exception('Не удалось найти background-image!')

    img_base64 = m.group(1).encode('utf-8')
    img_data = b64decode(img_base64)

    # Приводим к RGB, т.к. одновременно встречались разные цвета: RGB, RGBA, LA
    img = Image.open(BytesIO(img_data)).convert('RGB')

    # Картинки имеют однородный цвет
    return img.getpixel((0, 0))


def pixel_matches_color(
        rgb1: tuple[int, int, int],
        rgb2: tuple[int, int, int],
        tolerance: int = 20,
) -> bool:
    r, g, b = rgb1
    ex_r, ex_g, ex_b = rgb2
    return (abs(r - ex_r) <= tolerance) and (abs(g - ex_g) <= tolerance) and (abs(b - ex_b) <= tolerance)


soup = BeautifulSoup(open('rutor.live.htm', encoding='utf-8'), 'html.parser')

target_el = soup.select_one('#content > div[style*="background-image"]')
target_rgb = get_rgb(target_el['style'])
print('target_rgb:', target_rgb)

for variant_el in soup.select('#content em[style*="background-image"]'):
    variant_rgb = get_rgb(variant_el['style'])
    print('variant_rgb:', variant_rgb, pixel_matches_color(variant_rgb, target_rgb))

Результат:

target_rgb: (1, 9, 254)
variant_rgb: (255, 0, 0) False
variant_rgb: (255, 255, 0) False
variant_rgb: (0, 128, 0) False
variant_rgb: (0, 0, 0) False
variant_rgb: (128, 128, 128) False
variant_rgb: (0, 0, 255) True

Как видно, скрипт успешно вытащил картинки из тегов, получил их RGB и нашел самый похожий цвет среди вариантов