Взлом reCAPTCHA v2
Назойливая игра — разметка данных для google. Если, занимаетесь сбором доступной информации с ресурсов, не принадлежащим вам, и не сумели реализовать решение для преодоления этой преграды, советы от начинающего разработчика вам помогут. Опишу один из способов, основанный на детекторе объектов, хорошо справляется с типом 4×4, хуже с 3×3. Использую архитектуру YOLO, «золотая середина» точности/производительности, подход одинаков для всех детекторов. В коммерческом продукте стоит использовать «ансамбль» нейронных сетей, к детектору добавить классификацию каждой ячейки, это повысит общую точность с приемлемой производительностью. Также эту задачу можно решить, использую обучение с подкреплением A2C/DQN или любую современную архитектуру, трансформеры, генеративно-состязательные сети.
Примерный алгоритм
- Поиск позиции кнопки
- Имитация движения мыши к координатам кнопки «Я не робот»
- Имитация нажатия кнопки «Я не робот»
- Получение картинки ( с сервера google, посылается целой )
- Получение класса искомого объекта ( из html )
- Получение координат ячеек ( из html )
- Решение
- Активация ячеек исходя из решения
- Нажатие готово/далее/подтвердить
- Обработать
Если reCaptcha продолжается, повторить с 4 по 10.
Полезные инструменты в Python
- pynput
- selenium
- numpy
- tensorflow
- opencv
- scipy
- beautiful soup, можно обойтись одним selenium
Код найден в просторах моей нейронной сети, значит что то видел в интернет сети, живу не в вакууме
from selenium import webdriver from selenium.webdriver.firefox.options import Options 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.webdriver.common.by import By from pynput.mouse import Button, Controller import scipy.interpolate as si import numpy as np import cv2 import time import random import os import io import base64 # использование B-сплайна для имитации человеческих движений мыши def human_like_mouse_move(action, start_element): points = [[6, 2], [3, 2],[0, 0], [0, 2]]; points = np.array(points) x = points[:,0] y = points[:,1] t = range(len(points)) ipl_t = np.linspace(0.0, len(points) - 1, 100) x_tup = si.splrep(t, x, k=1) y_tup = si.splrep(t, y, k=1) x_list = list(x_tup) xl = x.tolist() x_list[1] = xl + [0.0, 0.0, 0.0, 0.0] y_list = list(y_tup) yl = y.tolist() y_list[1] = yl + [0.0, 0.0, 0.0, 0.0] x_i = si.splev(ipl_t, x_list) y_i = si.splev(ipl_t, y_list) startElement = start_element action.move_to_element(startElement); action.perform(); c = 5 i = 0 for mouse_x, mouse_y in zip(x_i, y_i): action.move_by_offset(mouse_x,mouse_y); action.perform(); print("Move mouse to, %s ,%s" % (mouse_x, mouse_y)) i += 1 if i == c: break; # "конфигурирование" selenium def my_proxy(PROXY_HOST,PROXY_PORT): fp = webdriver.FirefoxProfile() fp.set_preference("network.proxy.type", 1) fp.set_preference("network.proxy.socks",PROXY_HOST) fp.set_preference("network.proxy.socks_port",int(PROXY_PORT)) fp.update_preferences() options = Options() options.headless = True # отключаем визуализацию происходящего return webdriver.Firefox(executable_path="geckodriver/geckodriver", options=options, firefox_profile=fp) # с tor прокси, reCaptcha будет вечной, # хорошо для экспериментов proxy = my_proxy("127.0.0.1", 9050) proxy.get("https://www.google.com/search?q=apple")
После запроса, по понятным многим причинам, появляется reCaptcha.
# reCaptcha отображается в iframe's # переключение iframe №1 proxy.switch_to.frame(proxy.find_elements_by_tag_name("iframe")[0]) # находим кнопку "Я не робот" check_box = WebDriverWait(proxy, 10).until(EC.element_to_be_clickable((By.ID ,"recaptcha-anchor"))) time.sleep(2) # имитируем нажатие кнопки "Я не робот action = ActionChains(proxy); human_like_mouse_move(action, check_box) check_box.click() time.sleep(2)
Получаем информацию для дальнейшей обработки: ссылка на изображение, класс поиска, тип reCaptcha.
# переключение iframe №2 proxy.switch_to.default_content() iframes = proxy.find_elements_by_tag_name("iframe") proxy.switch_to.frame(iframes[2]) html = proxy.page_source # получаем ссылку изображения, тип reCaptcha try: img_rc = proxy.find_elements_by_xpath('//img[@class="rc-image-tile-33"]')[0] t_type = 3 except IndexError: img_rc = proxy.find_elements_by_xpath('//img[@class="rc-image-tile-44"]')[0] t_type = 4 # получаем искомый класс try: required_class = proxy.find_elements_by_xpath('//div[@class="rc-imageselect-desc-no-canonical"]/strong')[0].text except IndexError: required_class = proxy.find_elements_by_xpath('//div[@class="rc-imageselect-desc"]/strong')[0].text time.sleep(2)
Скачиваем изображение с сервера, не самым «элегантным способом». Встраиваем код javascript, что бы выполнить XMLHttpRequest, полученный ответ отобразить в canvas, для дальнейшей передачи в python строкой base64. После получения base64, преобразовываем в numpy array. Альтернативное получение изображения, описано в статье https://habr.com/ru/post/449236/
answ = proxy.execute_script(''' var img = new Image(); var cnv = document.createElement('canvas'); cnv.id = 'tutorial'; img.onload = function() < cnv.height = img.height; cnv.width = img.width; console.log(cnv.width, cnv.height, img.width, img.height); cnv.getContext('2d').drawImage(img, 0, 0); >var request = new XMLHttpRequest(); request.open('GET', arguments[0].src); request.responseType = 'blob'; request.onload = function() < var reader = new FileReader(); reader.readAsDataURL(request.response); reader.onload = function(e)< img.src = e.target.result; >; >; request.send(); var child = document.body.appendChild(cnv); ''', img_rc) time.sleep(4) answ = proxy.execute_script(''' cnv = document.getElementById('tutorial'); return cnv.toDataURL('image/jpeg').substring(22); ''') nparr = np.asarray(bytearray(io.BytesIO(base64.b64decode(answ)).read()), dtype=np.uint8) img_np = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
Получены все нужные компоненты, для ответа на вопрос: «в каком квадрате находиться искомый объект». На этом ресурсе не целесообразно в очередной раз описывать архитектуру YOLO детектора, поэтому демонстрирую фрагменты кода нужные этой статье.
def draw_boxes(image, boxes, scores, labels, classes, detection_size, search_class): """ :param boxes, shape of [num, 4] :param scores, shape of [num, ] :param labels, shape of [num, ] :param image, :param classes, the return list from the function `read_coco_names` """ new = np.ones(shape=image.shape, dtype=np.float32) ans = [] if boxes is None: return ans, image, new for i in range(len(labels)): # for each bounding box, do: bbox, score, label = boxes[i], scores[i], classes[labels[i]] bbox_text = "%s %.2f" %(label, score) # convert_to_original_size detection_size, original_size = np.array(detection_size), np.array(image.shape[1]) ratio = float(original_size) / float(detection_size) bbox = list((bbox.reshape(2,2) * ratio).reshape(-1)) coord = [abs(int(x)) for x in bbox] # встраиваем наш плохой код o0 = coord[0] o1 = coord[1] o2 = coord[2] o3 = coord[3] # создаем маску искомых объектов if search_class == label.split('\n')[0]: new[o1:o3, o0:o2, :] = 2 ans.append(classes[labels[i]]) return ans, image, new # основная функция для получения ответа def imcr(i, col, activation_threshold = 1): answ = [] im_w, im_h, im_c = i.shape w, h = im_w//col, im_h//col sZero = i[0:w, 0:h,:].size num = 0 for wi in range(0, col): for hi in range(0, col): num += 1 P_R = (np.sum(i[wi*w:(wi+1)*w, hi*h:(hi+1)*h, :]) / sZero) * 100 P_R = P_R - 100 if activation_threshold < int(P_R): answ.append(num) else: pass return answ def ocr(img_np, required_class, t_type): # img_np ->YOLO -> B,C # выполняем функцию не максимального подавления boxes, scores, labels = cpu_nms(B, C, len(classes), max_boxes=1000, score_thresh=0.4, iou_thresh=0.5) # встроил свой плохой код в чужой код визуализации данных result, img, z_image = draw_boxes(img_np, boxes, scores, labels, classes, yolo_image_shape, required_class) # наша основная функция answ = imcr(np.array(z_image), t_type)
Наша основная функция, imcr(image_array, type_captcha, activation_threshold) — получая маску искомого объект, функция проверяет процент заполнения в каждой ячейке по заданному условию
- параметры:
image_array — маска объекта
type_captcha — тип картинки, пример 4 (4×4)
activation_threshold — заданное условие активации, по умолчанию 1% - возвращает:
номера искомых ячеек в списке
Получаем ответ, имитируем нажатие нужной ячейки, подтверждаем.
answ_ocr = ocr(img_np, required_class, t_type) ids = proxy.find_elements_by_xpath('//td[@class="rc-imageselect-tile"]') for i in answ_ocr: ids[i].click() # поиск кнопки подтверждения confirm_btn = WebDriverWait(proxy, 4).until(EC.element_to_be_clickable((By.XPATH ,'//button[@id="recaptcha-verify-button"]'))) #Нахожу кнопку action = ActionChains(proxy); human_like_mouse_move(action, confirm_btn) # двигать курсор к кнопке confirm_btn.click() # нажать
Это не детальное руководство, а советы с фрагментами кода. Если применять предложенный подход, с другими алгоритмами, точность 93% и выше. Используя детектор, ваша главная задача повысить точность детектора (YOLO, RCNN, SSD). Также, одно из условий успешного обхода google captcha, использование «чистых proxy». У меня не особо получается преобразовывать свои мысли в текст, надеюсь попытка успешна, и моя статья появиться на этом ресурсе.
Как байпасить reCaptcha V3 с помощью Selenium Python?
Мы будем использовать библиотеку python Selenium для байпаса google reCaptcha v3. Следуйте пошаговой инструкции, чтобы получить результат.
Для примера мы будем использовать демо-версию Google reCaptcha api.
Сначала необходимо отключить настройку защиты контента в браузере Chrome.
Для этого зайдите в Настройки в Chrome. И напишите «настройки сайта» в строке поиска.
Перейдите в настройки сайта и найдите «Защищенный контент».
Перейдите к защищенному контенту и отключите его.
Теперь перейдем к части кодирования.
В этой статье мы будем работать с Python 3. Мы будем использовать две библиотеки. Если вы хотите настроить Selenium и узнать, как это сделать — изучите эту статью.
Установите библиотеку Beautiful Soup для скрипта.
pip install beautifulsoup4
Откройте файл-скрипт и импортируйте в него упомянутые библиотеки.
from selenium import webdriver from selenium.webdriver.common.keys import Keys from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.by import By from http_request_randomizer.requests.proxy.requestProxy import RequestProxy import os, sys import time,requests from bs4 import BeautifulSoup
Установите «delayTime» и «audioToTextDelay» в соответствии с вашей скоростью интернета. Установленные значения работают для всех.
delayTime = 2 audioToTextDelay = 10
byPassUrl — это URL, на который вам нужно ориентироваться. Опция используется для выбора драйвера chrome, и ей передаются некоторые аргументы.
filename = ‘1.mp3’ byPassUrl = ‘https://www.google.com/recaptcha/api2/demo' googleIBMLink = ‘https://speech-to-text-demo.ng.bluemix.net/' option = webdriver.ChromeOptions() option.add_argument('--disable-notifications') option.add_argument("--mute-audio")
Остальная часть кода приведена ниже. Теперь я объясню, как это работает.
Когда скрипт запускается, проверяется поле I’m not a robot.
И дальше все появляется (как обычно).
После по скрипту выбирается кнопка аудио внизу слева.
И появляется вот это. После этого загружается аудио с именем «1.mp3».
Это займет несколько секунд, не волнуйтесь. После этого в браузере откроется новая вкладка, которая перейдет от речи watson к конвертеру в текст и загрузит файл.
Как видите, аудиофайл преобразуется в текст. Он копирует текст и вставляет его в текстовое поле.
И далее нажимается кнопка «Проверить».
Вот, смотрите. Проблема решена. Если у вас есть какие-либо проблемы и вопросы, пишите. Я отвечу на них как только смогу.