Русский
Русский
English
Статистика
Реклама

Перевод Обход капч с помощью Headless Chrome

Использование 2Captcha and Puppeteer для автоматического прохождения капч



Вот уже лет десять мы видим капчи по всему интернету. Все эти волнистые линии, слова или числа, мешающие нам при попытке залогиниться, зарегистрироваться или написать где-нибудь комментарий.


image

Amazons CAPTCHA fallback


КАПЧА (от CAPTCHA англ. полностью автоматизированный и общедоступный тест Тьюринга для различения компьютеров и людей) задумана как врата, которые пропускают людей и отсеивают роботов (программ). Волнистые линии и слова сейчас уже не так распространены их заменила вторая версия реКАПЧИ от Google. Эта капча выдает вам зеленую галочку, если ваш коэффициент человечности оценивается как достаточно высокий.


image

Если же вы не дотянули до заданного порога человечности, то реКАПЧА прибегает к использованию подобной паззлу картинки, которая на удивление эффективна скорее в том, чтобы еще сильнее действовать на нервы, по сравнению с расшифровкой пары слов.


image

При том, что людей КАПЧИ раздражают, их можно было бы и потерпеть, если бы они хотя бы выполняли свою работу, однако, зачастую гораздо проще автоматизировать их распознавание, чем постоянно доказывать, что вы человек.


Как работает 2Captcha


2Captcha решает много разных типов капчи. Для взаимодействия с 2Captcha используются два адреса: на in.php присылается задача и в ответ Вы получаете captcha_id, на res.php вы по captcha_id получаете ответ, когда он будет готов.


2Captcha решает капчи в нескольких различных стилях с помощью двух, по большей части одних и тех же, конечных точек обработки запросов. Первый запрос передает данные, необходимые для решения капчи, и возвращает ID запроса. В случае капчи на основе изображения, данные будут изображением самой капчи, закодированным в 64base.


image

После получения ID запроса, вам нужно будет повторно отправлять его на сервер 2капчи, пока решение не будет готово.


image

С Recaptcha V2 история немного другая. Вы по-прежнему имеете дело с двухступенчатым процессом, что и представленный выше, но отправляете другие данные. Теперь вам нужно отправлять публичный ключ рекапчи (reCAPTCHA sitekey), который можно найти среди атрибутов элемента-контейнера капчи, независимо от того, был ли загружен
image

Получаемый ответ это токен, который нужно отправить вместе с формой и ввести в скрытое текстовое поле с идентификатором g-recaptcha-response. Скриншот ниже показывает, где оно находится, и я специально отключил CSS-свойство display: none, чтобы показать его на странице. Имея возможность редактировать это поле, вам будет проще вручную протестировать ответ 2Captcha, чтобы сократить количество переменных при тестовой интеграции.


image

Для капч, основанных на изображениях, результат доступен почти мгновенно. Для реКАПЧ версии 2 может потребоваться от 15 до 30 секунд.


Автоматизация через Puppeteer


Прежде чем беспокоиться о капче, нужно разобраться со всем прочим, но прежде чем мы сможем это сделать, нужно определиться с нашими инструментами. 3 причины, по которым в данном посте мы будем использовать Googles Chrome:


  1. В нем все очень легко автоматизируется через Puppeteer API.
  2. На нем можно работать как в headless-режиме, так и с графическим интерфейсом, что очень удобно и практично.
  3. Это самый распространенный в мире браузер, поэтому все имеющиеся на сайтах приемы анти-автоматизации имеют меньший шанс срабатывания (например, блокировка Selenium или PhantomJS)

Использование Puppeteer


Необязательно устанавливать хром, если не хочется, в Puppeteer есть все необходимое, в том числе Chromium. Но можете использовать и локально установленный Chrome, решать вам.


$ npm install puppeteer

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


const puppeteer = require('puppeteer');const chromeOptions = {  headless:false,  defaultViewport: null};(async function main() {  const browser = await puppeteer.launch(chromeOptions);  const page = await browser.newPage();  await page.goto('https://old.reddit.com/login');})()

В этом коде мы указываем два свойства конфигурации при запуске: headless: false, чтобы видеть то, что мы делаем, и defaultViewport: null, чтобы учесть неприятный визуальный глитч, при котором область просмотра не заполняет окно. Ни тот, ни другой не важны для работы браузера в headless-режиме, просто с ними удобней видеть и, что самое важное, делать скриншоты. Например, такой:


image

Это было просто! Теперь мы готовы перейти к следующему шагу автоматизировать регистрацию так, будто капчи никогда и не было. Вот где возможность включать/ выключать headless-режим будет полезна, ведь мы можем управлять браузером от лица человека, когда нужно. Сначала следует понять, как получить доступ к элементам на странице, которые нужно поменять. Запустите браузер и просмотрите открытую страницу через инструменты разработчика Google Chrome (горячая клавиша F12). Далее, найдите текстовые поля, которые нужно будет изменить. (горячие клавиши: +Shift+C на Mac и Ctrl+Shift+C на Windows) В случае с Reddit, нам нужно получить прямой доступ к полю ввода логина, двум полям ввода пароля и кнопке. Электронная почта необязательна, так что можем ее проигнорировать. Печать в текстовых полях через API библиотеки Puppeteer почти до смешного проста: вы просто передаете селектор, который идентифицирует элемент, и желаемую строку с помощью метода .type().


await page.type('#user_reg', 'some_username');await page.type('#passwd_reg', 'SuperStrongP@ssw0rd');await page.type('#passwd2_reg', 'SuperStrongP@ssw0rd');

Производить операции с кнопкой так же удобно, разве что у кнопки на странице Reddit нет связанного с ней идентификатора, так что нам нужен более сложный селектор. Если вы не знакомы с селекторами CSS, то для краткого ознакомления посмотрите Mozilla Developer Network.


await page.click('#register-form button[type=submit]');

Вот и всё! Протестируйте скрипт, чтобы удостовериться, что отправка логина работает. Из-за КАПЧИ, конечно, ничего не получится, но зато мы можем протестировать работу хуков.


image

Подождите-ка! Мы ведь даже не видим капчу, и консоль JavaScript жалуется на ошибки. Что здесь происходит? Во время автоматизации веб-страниц, помимо капч, есть множество других препятствий, которые могут встать у вас на пути. И одна из них настолько высокая скорость выполнения операций, что страница ломается. Когда браузеры автоматизированы, они работают во много-много раз быстрее, чем на то способен обычный человек, и зачастую это приводит к выполнению кода в таком порядке, в каком разработчики его не тестировали (это называется состоянием гонки или неопределённость параллелизма).


Страница Reddit страдает от состояния гонки, тогда как Google выводит реКАПЧУ после фокусировки на втором поле ввода пароля. То есть наш скрипт выполняется c такой скоростью, что смена фокуса происходит до того, как готов скрипт реКАПЧИ. Есть много решений этой проблемы, но самое простое добавить минимальную задержку, необходимую, чтобы миновать это состояние гонки. Мы могли бы добавить хуки и обработчики событий, чтобы убедиться, что мы действуем только после того, как рекапча загрузилась, но, похоже, самих разработчиков Reddit состояние гонки устраивает, так что нам нет необходимости умничать. Есть много способов организовать задержку, но в опциях Puppeteer, связанных с запуском браузера, есть параметр slowMo, который глобально задерживает все действия на заданное значение. Это очень грубый подход, так как замедляются вообще все действия Puppeteer, но начать с этого можно.


const chromeOptions = {  headless:false,  defaultViewport: null,  slowMo:10,};

После добавления этой опции мы видим, что капча снова работает. Ради забавного эксперимента, можно попробовать пройти капчу прямо сейчас и посмотреть что будет. Поскольку мы используем вариант Chromium с настройками по умолчанию, который запускается библиотекой Puppeteer, и мы управляем им через средства автоматизации, то реКАПЧА будет изо всех сил пытаться доказать, что мы не человек. Вам, вероятно, придется пройти несколько уровней проверки, даже если вы разберетесь со всеми картинками. Когда я тестировал это, мне пришлось пройти через 10 различных повторений, прежде чем я получил зеленую галочку.


К счастью, все это можно сделать намного легче.


Настройка 2Captcha


2Captcha требует API ключ, который выдается при регистрации. Вам также потребуется какое-то количество средств, потому что, не всё в жизни бесплатно. И просто ради смеха, конечно же, вам понадобиться пройти КАПЧУ.


`http://2captcha.com/res.php?key=${apiKey}&action=get&id=${reqId}`;

2Captchas API работает через двухступенчатый процесс, где вы отправляете данные КАПЧИ и получаете результат после возврата ID запроса. Поскольку мы имеем дело с reCaptcha v2, нам нужно будет отправить публичный ключ Reddit, о котором говорилось ранее. Нам также нужно убедиться, что мы выбрали метод userrecaptcha и отправляем URL страницы, на которой расположена реКАПЧА.


const formData = {  method: 'userrecaptcha',  key: apiKey, // your 2Captcha API Key  googlekey: '6LeTnxkTAAAAAN9QEuDZRpn90WwKk_R1TRW_g-JC',  pageurl: 'https://old.reddit.com/login',  json: 1};const response = await request.post('http://2captcha.com/in.php', {form: formData});const requestId = JSON.parse(response).request;

После того как вы сделали этот запрос и получили обратно идентификатор запроса, вам нужно запросить URL res.php, используя ваши ключ API и идентификатор запроса, чтобы получить ответ.


<a href="`http://2captcha.com/res.php?key=${apiKey}&action=get&id=${reqId}`;"></a>

Если ваша капча не готова, вы получите ответ CAPTCHA_NOT_READY, что указывает на то, что нужно попробовать ещё раз через секунду или две. Когда капча готова, ответом будут данные, соответствующие выбранному методу отправки. Для капчи, основанной на изображении это будет решение. Для reCaptcha V2 данные, которые нужно отправить в полях формы.


Для reCaptcha V2 время нахождения решения может различаться минимум 15 секунд, максимум 45. Ниже показан пример механизма опроса, но в этот раз простого запроса по URL, который может быть интегрирован в ваше приложение так, как вам будет удобно.


async function pollForRequestResults(  key,   id,   retries = 30,   interval = 1500,   delay = 15000) {  await timeout(delay);  return poll({    taskFn: requestCaptchaResults(key, id),    interval,    retries  });}function requestCaptchaResults(apiKey, requestId) {  const url = `http://2captcha.com/res.php?key=${apiKey}&action=get&id=${requestId}&json=1`;  return async function() {    return new Promise(async function(resolve, reject){      const rawResponse = await request.get(url);      const resp = JSON.parse(rawResponse);      if (resp.status === 0) return reject(resp.request);      resolve(resp.request);    });  }}const timeout = millis => new Promise(resolve => setTimeout(resolve, millis))

Как только у вас есть данные ответа, вам нужно вставить результат в скрытое текстовое поле g-recaptcha-response в форме регистрации Reddit. Это не так просто, как использование метода .type() библиотеки Puppeteer, так как элемент невидим и не может получить фокус ввода. Можно сделать его видимым и затем использовать .type(), или же использовать JavaScript, чтобы внедрить значение на страницу. Для добавления JavaScript на страницу, при использовании Puppeteer, у нас есть метод .evaluate(), который принимает либо функцию, либо строку (при передаче функции она просто преобразуется в строку с помощью метода .toString()), и запускает ее в контексте страницы.


const response = await pollForRequestResults(apiKey, requestId);const js = `document.getElementById("g-recaptcha-response").innerHTML="${response}";`await page.evaluate(js);

После внедрения этого значения у нас все готово для завершения регистрации. Это действительно так просто.


Полный скрипт доступен ниже, если вам захочется поэкспериментировать с Puppeteer и/или 2Captcha.


Что вы теперь можете сделать?


Этот пост был написан ради двух вещей:


  1. Показать вам, насколько капчи нехорошая вещь

и


  1. Показать вам, что капчам нет необходимости блокировать вас

Капчи существуют, как правило, чтобы блокировать нехороших субъектов, манипулирующих контентом в мошеннических или вредоносных целях в ходе спланированных атак, которые выливаются в многомиллионные запросы. Есть много легитимных причин, по которым вам может потребоваться программно управлять сайтом, и если капчи не останавливают плохих парней, то вас-то уж точно они останавливать не должны.

Источник: habr.com
К списку статей
Опубликовано: 26.06.2020 10:22:09
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Google chrome

Javascript

Node.js

Headless chrome

Puppeteer

Reddit

Captcha

Recaptcha

Категории

Последние комментарии

© 2006-2020, personeltest.ru