Скрипт, по открытию сайта и нажатия на нужный цвет(капча)
нужен скрипт, который будет выполнять запрос на определенный сайт, там есть 6 цветов (красный, желтый, синий, серый, черный и зеленый) Как только он находит нужный цвет(Они могут быть разные), тоесть выглядит так же
думаю все понятно, вот код, который я сделал, но я не думаю, что он работает, в чем проблема? так же хочу представить скрин с html кодом 
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.
Значит, действия:
- Вытащить элемент с нужным цветом. Для поиска использую CSS-селекторы
- Вытащить элементы с вариантами цвета
- Получить картинки элементов. Тут я использую вариант через
background-image - Найти нужный цвет
Для вытаскивания буду использовать 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 и нашел самый похожий цвет среди вариантов
