Создание JS парсеров. Работа с ReCaptcha2.

Пример разработки JS парсера для работы с рекаптчами

  1. Support
    ReCaptcha2 - это усовершенствованный вид каптчи. Для пользователя обычно это выглядит как чекбокс "Я не робот". Иногда после клика по чекбоксу появляется окно, в котором среди нескольких картинок нужно выбрать те, которые соответствуют указанному условию. Данный вид каптчи значительно сложнее в плане реализации и автоматизации процесса разгадывания.

    Но на данный момент уже существуют как онлайн, так и оффлайн решения. В A-Parser есть встроенный парсер Util::ReCaptcha2 Util::ReCaptcha2, который как раз и позволяет работать с такими решениями.

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

    Алгоритм работы с рекаптчами в А-Парсере практически такой же, как и для обычных каптч:
    1. Открываем страницу, на которой выдается рекаптча
    2. Парсим sitekey
    3. Отправляем sitekey, а также необходимые дополнительные параметры на разгадывание (на данный момент достаточно sitekey и ссылки на страницу, где была получена рекаптча)
    4. Получаем хэш-ответ
    5. Отправляем полученный хэш обратно на сайт и получаем нужную нам информацию
    В отличие от обычных каптч, на данный момент в А-Парсере еще нет отдельной JS функции для работы с рекаптчами. Но это абсолютно не мешает нам разгадывать рекаптчи в JS парсерах. Для примера будем использовать эту страницу: http://http.myjino.ru/recaptcha/test-get.php

    Как и в случае с обычными каптчами, сначала нужно проанализировать страницу. Используем Инструменты разработчика в Chrome.

    Открыв тестовую страницу, мы видим текстовое поле (которое позволяет передать данные, тем самым убедившись, что рекаптча решена правильно), чекбокс рекаптчи и кнопка "Отправить".
    [​IMG]
    Вводим в текстовое поле произвольные данные, отмечаем чекбокс рекаптчи (если нужно, то проходим через выбор картинок) и нажимаем кнопку "Отправить". Смотрим на вкладке Network в Инструментах разработчика Chrome, какой запрос и куда при этом отправляется. Видим, что отправляется GET запрос, в параметрах которого передается введенный текст и хэш-ответ рекаптчи. И если рекаптча разгадана верно, в ответ приходит страница с текстом "Success! You're in.", а также отображается введенный текст.
    [​IMG]
    Теперь, определив логику работы рекаптчи на странице, можно перейти к написанию парсера.

    Как и в примере с обычной каптчей, создаем и открываем новый парсер. Загружается небольшой шаблон, в котором мы редактируем "шапку": определяем какие переменные будет выводить парсер и определяем формат результата по-умолчанию. Также, прописываем выбор пресета настроек для Util::ReCaptcha2 Util::ReCaptcha2.
    Код:
    constructor() {
      this.defaultConf = {
        version: '0.1.6',
        results: {
          flat: [
            ['result', 'ReCaptcha result'],
          ]
        },
        results_format: '$result\\n',
        parsecodes: {
          200: 1,
        },
        max_size: 200 * 1024,
        Util_ReCaptcha2_preset: 'default'
      };
      this.editableConf = [
        ['Util_ReCaptcha2_preset', ['combobox', 'Util::ReCaptcha2 preset']]
      ];
    }
    Далее, в функции *parse(set, results) описываем каждый этап.
    Загружаем страницу, на которой выдается рекаптча, также проверяем на "удачность" запроса:
    Код:
    let response = yield this.request('GET', 'http://http.myjino.ru/recaptcha/test-get.php', {}, {
      decode: 'auto-html',
    });
    if(!response.success) {
      this.logger.put('Error open page');
      results.success = 0;
      return results;
    }
    Парсим sitekey (с проверкой "успешности"):
    Код:
    let sitekey;
    try {
      sitekey = response.data.match(/data-sitekey="([^"]+)/)[1];
    } catch(e) {
      this.logger.put('Sitekey not found');
      results.success = 0;
      return results;
    }
    Отправляем найденный sitekey и страницу, на которой он был получен на разгадывание (т.к. отдельной функции в отличие от обычной каптчи пока что нет, мы используем обращение к стандартному парсеру yield this.parser.request:
    Код:
    let ReCaptchaResp = yield this.parser.request('Util::ReCaptcha2', this.conf.Util_ReCaptcha2_preset, {}, sitekey + ' ' + 'http://http.myjino.ru/recaptcha/test-get.php')
    if(ReCaptchaResp.error != 'none') {
      this.logger.put('ReCaptcha recognize failed');
      results.success = 0;
      return results;
    }
    Отправляем полученный хэш-ответ GET-запросом на сайт:
    Код:
    response = yield this.request('GET', 'http://http.myjino.ru/recaptcha/test-get.php', {
      text: set.query,
      'g-recaptcha-response': ReCaptchaResp.resp
    }, {
      decode: 'auto-html',
    });
    if(!response.success) {
      this.logger.put('Error checking ReCaptcha');
      results.success = 0;
      return results;
    }
    Проверяем полученную страницу, если на ней есть текст Success! You're in - значит рекаптча была решена верно и в результат можно вывести сообщение об успехе, иначе ошибка разгадывания:
    Код:
    if(!/Success! You're in/.test(response.data)) {
      this.logger.put('Bad ReCaptcha answer');
      results.success = 0;
      return results;
    } else {
      this.logger.put('Good ReCaptcha answer');
      results.result = 'Success';
    }
    Возвращаем результат:
    Код:
    return results;
    Сохраняем парсер и проверяем его в работе. В данном случае, поданный на вход запрос будет передан на результирующую страницу, но по факту начальный запрос ни на что не влияет.
    [​IMG]
    Как видим, парсер составлен правильно и рекаптча правильно решается.

    Данный пример демонстрирует работу с ReCaptcha2 в JS парсерах. При написании более сложных парсеров алгоритм может отличаться, но в целом общий подход именно такой, как описано выше.

    P.S. Аналогично примеру для обычных каптч, в данном случае также рекомендую делать вначале проверку на выбор пресета настроек Util::ReCaptcha2 Util::ReCaptcha2. Пример такой проверки:
    Код:
    if(this.conf.Util_ReCaptcha2_preset == 'default') {
      this.logger.put('Select ReCaptcha2 preset');
      results.success = 0;
      return results;
    }
    Полностью готовый парсер можно забрать здесь.