Как стать автором
Обновить

Решение Амазон капчи Waf Captcha на полном автомате, имея за плечами практически нулевой опыт в разработке

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров1.7K

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

Собственно к чему все это? Да к тому, что когда мне потребовалось решить капчу от Амазон, пресловутую Waf Captcha я пошел копать на сервис, которым постоянно пользуюсь при работе с Кей Коллектором, и некоторыми другими сервисами (2капча - жаль Хабр банит статьи за реферальные ссылки).

Ну и нашел там инструкцию, ссылку на которую собственно и привел выше. Как вам вероятно стало понятно из эпиграфа - я ни черта не понял, вернее я понял, что надо использовать АПИ, но на этом все...

С Селениумом было реально проще.

Главная проблема - малый таймаут, который выделяется на решение со стороны Амазона. Время на решение капчи ограничено и если ответа нет, то капча обновляется (у нее обновляются 2 параметра - iv и context).

Получается, что таймаут свежести капчи около 30 секунд, а за это время необходимо найти на странице параметры, скопировать их, вставить в код скрипта и запустить его, после этого 2капча должна ее решить и вернуть правильный ответ. Я пробовал это сделать пару безуспешных часа, вырабатывал автоматизм действий, но увы, на поиск и замену изменяемых параметров уходит не менее 12-15 секунд, и остается от 15 до 18 секунд мы решение капчи сервисом, что в нынешних реалиях звучит достаточно фантастически.

Тут нужен другой подход, искать и подставлять параметры должен скрипт, но как его написать человеку, который в своей жизни ничего сложнее Ahrefs не видел?

Вот именно по этой причине, я считаю, что инструкции, подобные упомянутым в статье необходимо делать более подробными, чем - "Просто используй Апи, ты че совсем куку?"

Решение

По итогу решение было найдено и заняло оно у меня примерно 3 часа времени. Рассказываю, как же джуну решить Амазон капчу на полном автомате.

Нам понадобится GPT Chat и в моем случае видео распознавания Амазон капчи (вам оно не понадобится, так как я дам вам уже готовый собранный файл).

Видео я взял у знакомого проггера, но он запретил его выкладывать в паблик, так как оно не обезличено.

Но вы же не отстанете от меня,будете просить пруфы, а я потом подсяду на антидепресанты, что мне никто не верит, поэтому я воспроизвел это видео в самом конце, когда получил готовый скрипт и срадостью приложу его в самом конце этого текста, в качестве демонстрации моей бесконечной преданости аудитории!

Итак, поехали по порядку:

Я взял видео, сделал 3 скриншота и загрузил их в GPT Chat и попросил его переписать мне этот код текстом.

В видео было несколько файлов, но показано только содержимое 2 из них - index.js и inject.js - с них я и начал.

Не буду утомлять вас расшифровкой скринов (там пришлось немного повозиться и собрать код со скриншотов в единое целое но по итогу я получил два вот таких куска кода для двух файлов:

// index.js
import { launch } from 'puppeteer'
import { Captcha } from '2captcha-ts'
import { readFileSync } from 'fs'

const solver = new Captcha(process.env.APIKEY)

const target = 'УРЛ сайта где встречается капча'

const example = async () => {
  const browser = await launch({
    headless: false,
    devtools: true
  })

  const [page] = await browser.pages()

  const preloadFile = readFileSync('./inject.js', 'utf8')
  await page.evaluateOnNewDocument(preloadFile)

  // Here we intercept the console messages to catch the message logged by inject.js script
  page.on('console', async (msg) => {
    const txt = msg.text()
    if (txt.includes('intercepted-params:')) {
      const params = JSON.parse(txt.replace('intercepted-params:', ''))

      const wafParams = {
        pageurl: target,
        sitekey: params.key,
        iv: params.iv,
        context: params.context,
        challenge_script: params.challenge_script,
        captcha_script: params.captcha_script
      }
      console.log(wafParams)

      try {
        console.log('Solving the captcha...')
        const res = await solver.solveRecaptchaV2(wafParams)
        console.log(`Solved the captcha ${res.id}`)
        console.log(res)
        console.log('Using the token...')
        await page.evaluate(token => {
          window.localStorage.inputCaptchaToken(token)
        }, res.data.captcha.voucher)
        console.log(e)
      } catch (e) {
        console.log(e)
      }
    }
  })

  await page.goto(target)
  // Additional code to interact with the page after captcha is solved might be here...
}

example()

И второй файл inject.js

console.clear = () => console.log('Console was cleared')

const i = setInterval(() => {
  if (window.CaptchaScript) {
    clearInterval(i)

    let params = gokProps

    Array.from(document.querySelectorAll('script')).forEach(s => {
      const src = s.getAttribute('src')
      if (src && src.includes('captcha.js')) params.captcha_script = src
      if (src && src.includes('challenge.js')) params.challenge_script = src
    })

    console.log('intercepted-params: ' + JSON.stringify(params))
  }
}, 5)

Естественно, я уточнил у Чата, как мне заставить код работать, на что получил рекомендацию использовать стандартную команду

node index.js

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

Изучив код, который я дал ему в виде скриншотов, он порекомендовал установить следующие пакеты

puppeteer

2captcha-ts

playwright

Единственно, я не совсем понял, нафига тут нужен playwright, но кто я такой, чтобы сомневаться в компетенции Чата.

И соответсвенно код установки npm install puppeteer 2captcha-ts playwright (правда у меня через VS Code не получилось их поставить все вместе, вероятно виной всему кривые руки, я ставил по одному и через консоль)

npm install puppeteer

npm install 2captcha-ts

npm install playwright

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

Итак, для корректной работы кода понадобился файл с кодировкой .env, причем он может быть без названия, а в этом файле должны быть следующие данные:

APIKEY=your_2captcha_api_key

Понятно, что вместо параметра your_2captcha_api_key я подставил свой ключ с сервиса.

Дальше было еще 6 рекомендаций, что надо делать чтобы код заработал, но

Соответсвенно первый запуск и первая ошибка.

Ошибка была связана с использованием синтаксиса ES6 import в Node.js. Для его использования нужно либо указать тип модуля в package.json, либо изменить расширение файла на .mjs.

Мне было лень указывать тип модуля в package.json и я пошел по пути наименьшего сопротивления, тупо переименовал расширение файла index с js на mjs.

Следующая ошибка была связана с подключаемым пакетом 2captcha-ts, но подробно описывать их не хочется, скажу лишь что я изменил код, отвечающий за запуск этого модуля несколько раз, добавил логирование и проверку корректности подключения файла .env.

И это все равно не сработало, скрипт продолжал выдавать ошибку и упорно не хотел работать. Я сравнил скриншот и код который мне вытащил оттуда Чат и нашел небольшую опечатку, которая и была корнем проблемы.

Но, как оказалось, и это не помогло - выпала ошибка APIKEY is not defined in .env file

Это мы пофиксили добавлением нового пакета:

dotenv

npm install dotenv

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

И в конце концов код файла index.js из вот такого:

// index.js
import { launch } from 'puppeteer'
import { Captcha } from '2captcha-ts'
import { readFileSync } from 'fs'

const solver = new Captcha(process.env.APIKEY)

const target = 'УРЛ сайта где встречается капча'

const example = async () => {
  const browser = await launch({
    headless: false,
    devtools: true
  })

  const [page] = await browser.pages()

  const preloadFile = readFileSync('./inject.js', 'utf8')
  await page.evaluateOnNewDocument(preloadFile)

  // Here we intercept the console messages to catch the message logged by inject.js script
  page.on('console', async (msg) => {
    const txt = msg.text()
    if (txt.includes('intercepted-params:')) {
      const params = JSON.parse(txt.replace('intercepted-params:', ''))

      const wafParams = {
        pageurl: target,
        sitekey: params.key,
        iv: params.iv,
        context: params.context,
        challenge_script: params.challenge_script,
        captcha_script: params.captcha_script
      }
      console.log(wafParams)

      try {
        console.log('Solving the captcha...')
        const res = await solver.solveRecaptchaV2(wafParams)
        console.log(`Solved the captcha ${res.id}`)
        console.log(res)
        console.log('Using the token...')
        await page.evaluate(token => {
          window.localStorage.inputCaptchaToken(token)
        }, res.data.captcha.voucher)
        console.log(e)
      } catch (e) {
        console.log(e)
      }
    }
  })

  await page.goto(target)
  // Additional code to interact with the page after captcha is solved might be here...
}

example()

Превратился в вот такой index.mjs

// index.js
import 'dotenv/config';
import { launch } from 'puppeteer'
import Captcha from '2captcha-ts';
import { readFileSync } from 'fs'

// Проверка наличия APIKEY в .env
if (!process.env.APIKEY) {
    console.error("APIKEY is not defined in .env file");
    process.exit(1); // Завершение выполнения, если ключ не найден
}

const solver = new Captcha.Solver(process.env.APIKEY);

const target = 'УРЛ сайта где встречается капча'

const example = async () => {
    const browser = await launch({
        headless: false,
        devtools: true
    })

    const [page] = await browser.pages()

    const preloadFile = readFileSync('./inject.js', 'utf8')
    await page.evaluateOnNewDocument(preloadFile)

    // Here we intercept the console messages to catch the message logged by inject.js script
    page.on('console', async (msg) => {
        const txt = msg.text()
        if (txt.includes('intercepted-params:')) {
            const params = JSON.parse(txt.replace('intercepted-params:', ''))

            const wafParams = {
                pageurl: target,
                sitekey: params.key,
                iv: params.iv,
                context: params.context,
                challenge_script: params.challenge_script,
                captcha_script: params.captcha_script
            }
            console.log(wafParams)

            try {
                console.log('Solving the captcha...')
                const res = await solver.amazonWaf(wafParams)
                console.log(`Solved the captcha ${res.id}`)
                console.log(res)
                console.log('Using the token...')
                await page.evaluate(async (token) => {
                    await ChallengeScript.submitCaptcha(token);
                    window.location.reload ()
                }, res.data.captcha_voucher);
            } catch (e) {
                console.log(e)
            }
        } else {
            return
        }
    })

    await page.goto(target)
    // Additional code to interact with the page after captcha is solved might be here...
}

example()

В коде выше не забудьте подставить верный урл, где требуется решение (если будете применять).

А из вот такого inject.js

console.clear = () => console.log('Console was cleared')

const i = setInterval(() => {
  if (window.CaptchaScript) {
    clearInterval(i)

    let params = gokProps

    Array.from(document.querySelectorAll('script')).forEach(s => {
      const src = s.getAttribute('src')
      if (src && src.includes('captcha.js')) params.captcha_script = src
      if (src && src.includes('challenge.js')) params.challenge_script = src
    })

    console.log('intercepted-params: ' + JSON.stringify(params))
  }
}, 5)

В вот такой inject.js

// console.clear = () => console.log('Console was cleared')

let counter = 0;
const MAX_ATTEMPTS = 2000; // Примерно 10 секунд при интервале в 5 мс
console.log('Начинаем поиск CaptchaScript...');

const i = setInterval(() => {
    console.log(`Попытка ${counter}: Проверяем наличие CaptchaScript...`);

    if (window.CaptchaScript || counter > MAX_ATTEMPTS) {
        clearInterval(i);
        if (!window.CaptchaScript) {
            console.log('CaptchaScript не найден');
        } else {
            console.log('CaptchaScript найден');

            let params = gokuProps;
            Array.from(document.querySelectorAll('script')).forEach(s => {
                const src = s.getAttribute('src');
                if (src && src.includes('captcha.js')) params.captcha_script = src;
                if (src && src.includes('challenge.js')) params.challenge_script = src;
            });

            console.log('intercepted-params: ' + JSON.stringify(params));
        }
    }
    counter++;
}, 5);

И скрипт заработал. Вот прям совсем. Решил капчу и продолжает ее решать при каждом запуске.

Получается будущее наступило, старик. Но это не точно.

Что вам делать с этой информацией? Ну, блин, мне очень нравиться совет - живи теперь с этим. Но, советы раздавать не хочется. Смотрите сами, может пригодится кому для своих проектов...

Теги:
Хабы:
Всего голосов 2: ↑2 и ↓0+2
Комментарии2

Публикации

Истории

Работа

Ближайшие события

Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
OTUS CONF: GameDev
Дата30 мая
Время19:00 – 20:30
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область