Закрыть
npm

Работа с капчей Редактировано: 28.08.2020 в 04:45

При работе с API ВКонтакте очень часто может возникнуть непредвиденная ошибка "картинки смерти". Это - капча. Когда Ваш скрипт отправляет по одному access_token'у слишком много запросов секунду, то сервер ВКонтакте приостанавливает его активность до тех пор, пока Вы не докажете, что Вы - не бот. Такая ошибка возникнет только при работе с токеном пользователя, в других ситуациях сервер ВКонтакте попросту временно заморозит Ваш токен.

После того, как сервер ВКонтакте "замораживает" токен пользователя, на любой его запрос будет возвращаться ошибка капчи. В этой ошибке имеются данные для решения капчи, основное - это SID капчи (ID капчи, прикрепленный к текущей сессии, токену), и URL капчи (URL адрес картинки капчи, переходя по которому скрипт сервера ВКонтакте автоматически сгенерирует изображение капчи с буквами)

Чтобы решить капчу, необходимо просто в любом следующем запросе отправить такие параметры, как captcha_sid, captcha_key (текст с картинки). Если все верно, то запрос будет выполнен.

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

# captchaHandler

Так как все запросы при работе с Easy VK происходят через метод vk.call(), то внутри него имеется основной хендлер - он отвечает за обработку всех ошибок внутри запроса. Это он распознает, какая именно произошла ошибка. И, если произошла ошибка капчи, он попробует запустить captchaHandler для ее решения.

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

{
  captcha_sid, // SID текущей капчи
  captcha_img,  // URL адрес капчи
  resolve,  // Callback функция для решения капчи resolve(key){...}
  vk // Объект EasyVK для работы в разной области видимости
}

Чтобы задать captchaHandler, необходимо добавить эту настройку в объект настройки Easy VK.

function captchaHandler ({captcha_sid, captcha_img:url, resolve:solve}) {
  // В этой функции Вы решаете капчу любым удобным Вам способом
  
  console.log(`Ой.. Надо решить капчу, URL = ${url}`)

  /* 
    ПСЕВДОКОД:  
    getCaptcha(url).then(key => {
      // Получили текст с картинки с помощью Вашего алгоритма
      solve(key).then(() => {
        console.log('Капча решена')
      }).catch(({err, reCall}) => {
        // Капча не решена, пробуем снова
        reCall()
      });
    })
  */
}

easyvk({
  captchaHandler: captchaHandler
}).then((vk) => {
  
  //...

}).catch(console.error)

Когда вы получите текст с картинки каким-либо способом, запустите callback функцию resolve (из основных параметров captchaHandler), которая возвращает объект <Promise>. Если капча не решена, в reject функцию этого Promis'а вернется следующий объект

{
  err, // Ошибка и ее описание
  reCall, // Функция для повторного запуска captchaHandler
  vk // Объект EasyVK
}

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

[+] (Спойлер) - Боевой пример работы captchaHandler
const readline = require('readline')
const easyvk = require('easyvk')

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

const captchaHandler = ({captcha_sid, captcha_img, resolve:solve, vk}) => {

  rl.question(`Введите капчу для картинки ${captcha_img} `, (key) => {

    // Когда вводится капча в консоль, пробуем решить капчу
    solve(key).then(() => {

      console.log('Капча решена корректно!')

    }).catch(({err, reCall: tryNewCall}) => {

      // Иначе капча не решена, стоит попробовать снова
      console.log('Капче не решена!!!\nПробуем занова')

      tryNewCall() // Пробуем снова, занова запускаем наш captchaHandler, по факту...

      // Не стоит самостоятельно перезапускать функцию captchaHandler, так как в EasyVK
      // для этого имеется функция reCall, которая точно запустит все как нужно

    })

  })

}

easyvk({
  captchaHandler: captchaHandler
}).then(vk => {

  // пример: vk.call('messages.send', ...)

}).catch(console.error)
    

С версии 2.6.0 captchaHandler работает также с HTTP Клиентом