Решение капч кликами на примере FunCaptcha и заработок на этом

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93
115229
Есть несколько способов решения капч с помощью сервисов:
  • Токеном
  • Прокликиванием картинок
  • Через расширение
В этой статье мы с вами рассмотрим второй способ на примере FunCaptcha, т.к. именно с ней я наиболее плотно работал последние пару месяцев. Освоив принципы, изложенные в статье, вы также сможете написать решение для hcaptcha, recaptcha или любой другой капчи, которую можно решить кликами.

Что нам с вами нужно для успешного решения капчи:
  • Уметь читать документацию API сервисов для решения капч, составлять запросы и обрабатывать ответы
  • Уметь получать задание и картинку со страницы
Важно: я не буду тут выкладывать полностью готовое решение. Отладка и доведение до ума уже ложится на ваши плечи, если оно вам действительно нужно.

Разбираемся с составлением запросов

Весь процесс будем рассматривать на примере Capmonster.cloud. Освоив работу с ним, вы сможете работать и с любым другим сервисом по решению капч.

Первым делом заходим на страницу с описанием API. Для этого достаточно вбить в поисковик «API название сервиса». Для capmonster.cloud - https://zennolab.atlassian.net/wiki/spaces/APIS/pages/589825

По сути нам с вами нужно сделать всего два запроса:
  • Создать задачу
  • Получить результат решения
Почти во всех сервисах документация условно поделена на две части: как в принципе создавать запросы и что нужно заполнять при решении конкретной капчи. Т.е. нет одной страницы, где пошагово будет описано, как и что делать.

115203


Перейдем на страницу создания задачи и посмотрим, что там есть.

115204


1 – урл, куда надо отправлять запрос
2 – тип данных. Почти всегда это json
3 – какие параметры надо передавать.
4 – тип параметра. Если это string, то заключаем в двойные кавычки. Если написано «объект», значит внутрь него будут вложены другие параметры
5 – обязательный или нет. Если не передать обязательный параметр, мы получим ошибку.
6 – описание

Давайте сразу перейдем в PM и заполним кубик POST запроса
115205

115206


1-урл (https://api.capmonster.cloud/createTask)
2-тип данных. Т.к. у нас в документации было прописано json, мы прописываем application/json
3 – тело запроса в формате JSON. JSON – это текстовый формат обмена данными. Заполняется в фигурных скобках в формате {“ключ”:”значение”}. Обратите внимание, что task у нас объект, поэтому в качестве значения выступает другой объект (поэтому я поставил фигурные скобки, но пока не заполнил содержимое). Также обратите внимание на значение ключа clientkey – оно будет подставлено из переменной cfg_apikey
4 – переменная, куда ляжет ответ от сервиса capmonster.cloud.

Чтобы заполнить task, нам надо перейти на страницу с нужной капчей. В нашем случае это FunCaptcha. Но сначала небольшое отступление.

Recaptcha, hCaptcha, FunCaptcha можно решить двумя способами – токеном и кликами. В первом случае решение идет токеном, т.е. вам будет прислан ответ в «текстовом» виде, который вы самостоятельно должны вставить на страницу и отправить сайту. Во втором случае вы высылаете сервису картинку, а он говорит, куда вам надо кликнуть. Мы работаем с вариантом №2.

Название нужного нам способа ComplexImageTask - https://zennolab.atlassian.net/wiki/spaces/APIS/pages/2293497857/ComplexImageTask+Funcaptcha+Funcaptcha
115207


Обратите внимание на параметры imageUrls и imagesBase64. В данном случае нам на выбор дается один из двух вариантов: либо мы высылаем массив урл (которые ведут на изображения), либо сами картинки в формате base64. Мы будем пользоваться вариантом №2. Давайте перейдем в PM и заполним содержимое нашего task
C#:
{
  "clientKey": "{-Variable.cfg_apiKey-}",
  "task": {
    "type": "ComplexImageTask",
    "class": "funcaptcha",
    "imageUrls": [
      "{-Variable.images-}"
    ],
    "metadata": {
      "Task": "{-Variable.issue-}"
    }
  }
}
Давайте сразу создадим и кубик для получения результата:
115208



И не забудьте создать переменные, которые мы использовали в кубиках (нажимаем на плюсик): cfg_apiKey, images, issue, taskId.

Добываем задание и картинку

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

В трафике отображаются все запросы, посылаемые браузером. Мы можем вытаскивать оттуда любые данные, в том числе и картинки. Давайте сначала потренируемся, а потом займемся уже капчей. Будем вытаскивать вот эту картинку и заголовок с сайта nashcsgo.com
115209



Включаем окно трафика

115210


Прописываем в кубике c# (выполняем это 1 раз перед началом работы с сайтом, чтобы не было проблем в zp)
C#:
instance.UseTrafficMonitoring = true;
Очищаем трафик, открываем devTools и вкладку NetWork, чтобы запросы также отображались и там тоже (помимо окна трафика) и переходим на сайт
115211

Выбираем img, чтобы отображались только картинки(1), жмём по любой картинке(2), выбираем preview, чтобы видеть сами картинки (3) и находим ту, что нам нужна.
115212


Жмём на Headers(1) и забираем урл картинки (2)
115213


Теперь отыщем наш заголовок. Для этого прям там же жмем ctrl+f и в появившемся окне вводим наш заголовок. Жмем enter
115214


Жмём на найденное совпадение (3). Жёлтым подчеркнут наш заголовок. Жмём на headers, чтобы забрать урл.

Теперь займёмся перебором всего трафика. Наша задача – выцепить два урл, которые мы с вами нашли и достать тело (т.е. то, что во вкладке response).

Сначала создайте две переменные - img_base64 для картинки и issue

переходим в кубик c#.
C#:
var traffic = instance.ActiveTab.GetTraffic();
project.SendInfoToLog($"количество запросов в трафике - {traffic.Count().ToString()}");
foreach (var t in traffic)
{
    //если в урл содержится images/skinsmin.jpg (картинка)
    if(t.Url.Contains("images/skinsmin.jpg"))
    {
        project.SendInfoToLog("нашли картинку");
   
        //дожидаемся полной прогрузки тела запроса
        t.WaitResponse(30, 2);
   
        //сохраняем в переменную "images" в формате base64 (создайте переменную вручную!)
        var imageBytes = t.ResponseBody;
        project.Variables["images"].Value = Convert.ToBase64String(imageBytes);
   
        //сохраняем на пк (этого делать не нужно, это просто для самопроверки)
        File.WriteAllBytes(project.Directory + @"\1.jpg", imageBytes);
   
    }

    //если урл равен https://nashcsgo.com/
    if(t.Url == "https://nashcsgo.com/")
    {
        project.SendInfoToLog("нашли заголовок");
        t.WaitResponse(30, 2);
   
        //сохраняем в переменную "issue" тело запроса
        var imageBytes = t.ResponseBody;
        project.Variables["issue"].Value = Encoding.UTF8.GetString(imageBytes, 0, imageBytes.Length);
    }
}

//проверка на пустоту и выход по ошибке
if(string.IsNullOrWhiteSpace(project.Variables["images"].Value)) throw new Exception("картинка не найдена");
if(string.IsNullOrWhiteSpace(project.Variables["issue"].Value)) throw new Exception("заголовок не найден");
Если вы всё сделали верно, то в переменной images у вас картинка в формате base64, в issue исходный код страницы (я уж не стал вычленять оттуда именно заголовок) и в папке проекта изображение 1.jpg (сохранил я её чисто для самопроверки, в рабочем проекте вы эту строчку убираете).

Хотел бы заострить ваше внимание на одном важном моменте – после того, как вы выполните этот код трафик будет очищен. Нет, визуально вы всё ещё будете его видеть, но если выполнить код ещё раз – то он уже не сработает. Важно держать это в голове.

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

Так, если что-то непонятно, лучше проделайте всё сами, ну а мы перейдем уже к капче. Тут будем делать тоже самое (почти). Выставляем в настройках английский профиль, т.к. нам нужно отсылать задание именно на английском языке
115215



Перейдем на github.com и начнем процесс регистрации, пока не дойдем до капчи. Откройте также chromeDevTools и вкладку Network, чтобы мы могли отыскать картинку.
115218


Что мы здесь видим? Во-первых, нам отдаётся изображение целиком, так что никаких дополнительным манипуляций не нужно. Во-вторых, нам подходят два урл: rtig/image и blob. Нам нужен rtig/image. Почему? Потому что blob не отображается в мониторе трафика. Почему? Вопрос не ко мне.
115219


C#:
var traffic = instance.ActiveTab.GetTraffic();
project.Variables["images"].Value = "";
project.SendInfoToLog($"количество запросов в трафике - {traffic.Count().ToString()}");
foreach (var t in traffic)
{
    if(t.Url.Contains("rtig/image"))
    {
        project.SendInfoToLog("нашли картинку");
   
        t.WaitResponse(30, 2);
   
        var imageBytes = t.ResponseBody;
        project.Variables["images"].Value = Convert.ToBase64String(imageBytes);
   
        File.WriteAllBytes(project.Directory + @"\1.jpg", imageBytes);
   
    }
}

//проверка на пустоту и выход по ошибке
if(string.IsNullOrWhiteSpace(project.Variables["images"].Value)) throw new Exception("картинка не найдена");
С заголовком немного сложнее. Он есть в трафике, но я не смог его однозначно идентифицировать. Поэтому мы просто заберем его со страницы.
C#:
//находим элемент с заданием
var issue = instance.ActiveTab.FindElementByXPath("//*[@id='root']//h2/span", 0);
if(issue.IsVoid) throw new Exception(«не нашли задание на странице»);

//убираем <strong>, </strong>, (1 of *) и пробелы и сохр в переменную issue
string noStrong = issue.InnerHtml.Replace("<strong>", "").Replace("</strong>","").Trim();
project.Variables["issue"].Value = noStrong.Replace(Regex.Match(noStrong, @”\(.*\)”).Value, @"").Trim();
project.SendInfoToLog("получили задание – " + project.Variables["issue"].Value);
А можно ли было картинку тоже вытащить из кода страницы, не прибегая к работе с трафиком? Можно, но некоторую сложность составляет то, что тут у нас blob изображения. Раньше я не знал как это сделать, но во время написания этой статьи наткнулся на способ. Сделать можно так (может кто предложит в комментариях решение без сохранения картинки на пк?)
C#:
//достаем наш урл
var imgBlob = instance.ActiveTab.FindElementByXPath("//img[@aria-live='assertive']", 0);
if(imgBlob.IsVoid) throw new Exception("не нашли картинку");
string styleBlob = imgBlob.GetAttribute("style");
string linkBlob = Regex.Match(styleBlob, @"blob:.*(?="")").Value;
if(string.IsNullOrWhiteSpace(linkBlob)) throw new Exception("не смогли достать урл картинки регуляркой");

//открываем в новой вкладке
instance.NewTab("1");
instance.ActiveTab.Navigate(linkBlob);
instance.ActiveTab.WaitDownloading();
Thread.Sleep(1000);

//сохраняем на пк
Bitmap b = new Bitmap(instance.ActiveTab.FindElementByXPath("//img", 0).DrawAsBitmap(true));
b.Save(project.Directory + @"\1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
b.Dispose();

//считываем с пк
byte[] massByte = File.ReadAllBytes(project.Directory + @"\1.jpg");
string base64 = Convert.ToBase64String(massByte);
return base64;
Отправка на распознование и получение результата

Зайдите в личный кабинет capmonster.cloud, скопируйте ключ и вставьте в переменную cfg_apikey
115220


Теперь у нас есть всё необходимое для отправки на сервис capmonster.cloud. Выполняем наш кубик create и смотрим, что нам прислали в ответ. Чтобы проверить, найдите запрос в трафике, нажмите по нему два раза мышкой и перейдите на вкладку ответ. Если там error id=0, значит всё ок
115221

Сделаем проверку на то, что errorId == 0. Если это не так, то выйдем по ошибке и выведем сообщение в лог. Я делаю регулярками (это неправильно, но мне так привычнее), вы можете делать как вам удобно (с помощью кубика json)
115222

errorId\":0



Достаем taskId из ответа и кладем в переменную taskId. Ставим паузу в 1 сек и делаем запрос на получение ответа.

(?<="taskId":)\d+

Тут вы можете получить следующие ответы:
  • Ready – капча решена
  • Processing – в процессе решения
  • ERROR_CAPTCHA_UNSOLVABLE – сервис не может решить капчу
115224

Нам нужно сделать обработку для всех трех вариантов (если непонятно сделайте себе на кубиках).
C#:
//проверяем на ERROR_CAPTCHA_UNSOLVABLE
string errorUnsolvable = Regex.Match(project.Variables["getResult"].Value, @"ERROR_CAPTCHA_UNSOLVABLE").Value;
if(!string.IsNullOrWhiteSpace(errorUnsolvable)) throw new Exception("ERROR_CAPTCHA_UNSOLVABLE");


//проверяем статус
string status = Regex.Match(project.Variables["getResult"].Value, @"(?<=status"":"").*?(?="")").Value;
if(string.IsNullOrEmpty(status)) throw new Exception("не смогли извлечь status из ответа - " + project.Variables["getResult"].Value);

switch(status)
{
    //получили processing
    case "processing":
        project.SendInfoToLog("капча в процессе решения");
        project.Variables["statusSolution"].Value = "processing";
        break;
    //получили ready
    case "ready":
        project.SendInfoToLog("капча решена");
        project.Variables["statusSolution"].Value = "ready";
        break;
    default:
        throw new Exception("не смогли определить статус (не processing и не ready) - " + status);
}
115226

Сразу скажу, что ERROR_CAPTCHA_UNSOLVABLE не так, чтобы редкое явление. Тяжелые задания сервисы вообще не решают и не будут решать. Легкими заданиями считаются те, где нужно повернуть что-то в направлении руки и самих вариантов не больше 5. Ещё недавно это были животные и capmonster.cloud успешно их решал, но сейчас, как видим, картинки обновили и capmonster.cloud с ними не справляется. Возможно, на момент выхода статьи нейросеть уже будет обучена и сможет решать такие задания.

Чтобы попадались легкие задания используйте хорошие прокси и движок хромиум.

Так что далее вам придется поверить мне на слово. Вам придет ответ такого вида:
{"solution":{"answer":[false,false,false,false,false,true],"metadata":null},"cost":0.00015,"status":"ready","errorId":0,"errorCode":null,"errorDescription":null}
Там где true – это нужная нам картинка. Соответственно, нам надо с вами посчитать, какая она. После этого жмем по стрелке нужное количество раз и отправляем ответ.
C#:
//узнаем сколько раз надо кликнуть по стрелке
project.Json.FromString(project.Variables["getResult"].Value);
var otv = project.Json.solution.answer.ToString().Split(',');
string countClickCapmonster = Convert.ToString(otv.Length - 1);
if(string.IsNullOrWhiteSpace(countClickCapmonster)) throw new Exception("не смогли получить сколько раз надо кликать по стрелке вправо CapmonsterCloud");
project.SendInfoToLog($"нужно кликнуть {countClickCapmonster} раз");

//находим стрелку вправо
HtmlElement rightArrow = instance.ActiveTab.FindElementByXPath("(//a/*/*[name()='circle']/following-sibling::*)[last()]|(//a/*/*[name()='circle'])[last()]", 0);
if(rightArrow.IsVoid) throw new Exception("не найдена стрелка для переключения картинок");

//щелкаем нужное количество раз
for(int i=0;i<Convert.ToInt32(countClickCapmonster);i++)
{
    rightArrow.Click();
    Thread.Sleep(1000);
}

//жмем submit
var buttonSubmit = instance.ActiveTab.FindElementByXPath("//button[text()='Submit']", 0);
if(buttonSubmit.IsVoid) throw new Exception("не найдена кнопка submit");
buttonSubmit.Click();
Thread.Sleep(3000);
project.SendInfoToLog("нажали на нужное изображение");
Теперь надо определить есть ли ещё задания. Если да, то снова ищем картинку в трафике и отправляем на сервис. Если нет, тогда определяем, успешно ли мы решили капчу и действуем исходя из этого (если неудачно, можем попытаться снова или можно выйти по ошибке)
//если стрелка вправо есть, значит задания ещё есть
HtmlElement rightArrow = instance.ActiveTab.FindElementByXPath("(//a/*/*[name()='circle']/following-sibling::*)[last()]|(//a/*/*[name()='circle'])[last()]", 0);
if(!rightArrow.IsVoid)
{
    project.SendInfoToLog("задания ещё есть, продолжаем решать");
    project.Variables["status"].Value = "process";
    return "";
}

//решено неверно
HtmlElement notRight = instance.ActiveTab.FindElementByXPath("//h2[contains(text(), 'That was not quite right.')]", 0);
if(!notRight.IsVoid)
{
    project.SendInfoToLog("капча была решена неверно");
    project.Variables["status"].Value = "notRight";
    return "";
}

//галочка
var galka = instance.ActiveTab.FindElementByXPath("//img[contains(@src, 'thub-api.arkoselabs.com/cdn/fc/assets/style-manager/assets')]", 0);
if(!galka.IsVoid)
{
    project.SendInfoToLog("капча решена верно");
    project.Variables["status"].Value = "ready";
    return "";
}

//если не смогли опрелелить
project.Variables["status"].Value = "unknown";
Теперь надо определить есть ли ещё задания. Если да, то снова ищем картинку в трафике и отправляем на сервис. Если нет, тогда определяем, успешно ли мы решили капчу и действуем исходя из этого (если неудачно, можем попытаться снова или можно выйти по ошибке)
C#:
//если стрелка вправо есть, значит задания ещё есть
HtmlElement rightArrow = instance.ActiveTab.FindElementByXPath("(//a/*/*[name()='circle']/following-sibling::*)[last()]|(//a/*/*[name()='circle'])[last()]", 0);
if(!rightArrow.IsVoid)
{
    project.SendInfoToLog("задания ещё есть, продолжаем решать");
    project.Variables["status"].Value = "process";
    return "";
}

//решено неверно
HtmlElement notRight = instance.ActiveTab.FindElementByXPath("//h2[contains(text(), 'That was not quite right.')]", 0);
if(!notRight.IsVoid)
{
    project.SendInfoToLog("капча была решена неверно");
    project.Variables["status"].Value = "notRight";
    return "";
}

//галочка
var galka = instance.ActiveTab.FindElementByXPath("//img[contains(@src, 'thub-api.arkoselabs.com/cdn/fc/assets/style-manager/assets')]", 0);
if(!galka.IsVoid)
{
    project.SendInfoToLog("капча решена верно");
    project.Variables["status"].Value = "ready";
    return "";
}

//если не смогли опрелелить
project.Variables["status"].Value = "unknown";
Задания со стрелками попадаются чаще всего. Но также есть ещё задания, где надо выбрать одну из 6 картинок. Все делается аналогично, только надо будет кликать по нужному изображению, а не по стрелке. Эту часть я вам оставляю в качестве самостоятельной работы.

Заработок на решении капч
115232

5 октября я на форуме разместил тему о продаже плагина для решения FunCaptcha. За прошедшее время было 23 продажи на общую сумму 71 000 руб + было пара индивидуальных заказов. Размещался я только на этом форуме. Вроде бы неплохо, но есть несколько нюансов:
  • Не считая пары человек, взявших плагин на месяц, последняя продажа с форума была 6 ноября.
  • 15 продаж для меня сделал партнер, т.е. мне просто повезло. Человек предложил приводить клиентов за часть дохода, и я согласился. Если бы не он, у меня было бы всего 8 продаж.
Помимо дохода с продажи плагина удалось получить доход с партнерок капч (что явилось для меня полной неожиданностью). Если кто не в курсе, то большинство сервисов решения капч позволяют к запросам добавлять свой идентификатор и когда пользователь решает капчу, то вам падает небольшой процент.

Я тут ни на что не рассчитывал и добавил его больше по приколу. Какого же было моё удивление, когда я в один из дней увидел у себя на балансе $30. Поначалу я даже не мог врубиться, откуда они взялись и только потом до меня дошло, что я же размещал идентификатор. Сейчас у меня на балансе $130. Не так уж и плохо с 23 клиентов.

Вот тут lord_alfred поделился своими цифрами, можете также глянуть. У capmonster.cloud также есть партнерка, но нужно написать в саппорт, чтобы вам дали доступ. Так что этот вариант также не стоит списывать со счетов.

На этом всё. Для закрепления материала также можете посмотреть видео, где мы разбираемся с Recaptcha.

 
Номер конкурса статей
Двадцатый конкурс статей

Вложения

Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

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

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

n0n3mi1y

Client
Регистрация
08.03.2017
Сообщения
1 232
Благодарностей
572
Баллы
113
Статья хорошая и описывает немало технических особенностей. Для себя подчеркнул момент с сохранением данных из элемента через конструктор Bitmap, спасибо.
Так как я тоже задумывался о освещении темы такого рода - как к этому отнеслись клиенты, которые оплатили решение, а вы потом выложили бесплатно это в конкурсную статью?
 
Последнее редактирование:

radv

Client
Регистрация
11.05.2015
Сообщения
3 785
Благодарностей
1 949
Баллы
113
Хороший пример по работе с такой капчей, :az: некоторые капчи проще решать кликами, чем другими способами.
 

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93
Статья хорошая и описывает немало технических особенностей. Для себя подчеркнул момент с сохранением данных из элемента через конструктор Bitmap, спасибо.
Так как я тоже задумывался о освещении темы такого рода - как к этому отнеслись клиенты, которые оплатили решение, а вы потом выложили бесплатно это в конкурсную статью?
Да я же не выложил полностью готовое решение, это скорее заготовка. Не думаю, что из-за этого будут проблемы. Тут скорее ты мог бы отнестись негативно, если считаешь, что это как-то может повредить твоим продажам. А клиентов сейчас больше волнует, что вчера единственный сервис (на сколько я знаю), решающий токеном, "приказал долго жить".
 

n0n3mi1y

Client
Регистрация
08.03.2017
Сообщения
1 232
Благодарностей
572
Баллы
113
Да я же не выложил полностью готовое решение, это скорее заготовка. Не думаю, что из-за этого будут проблемы. Тут скорее ты мог бы отнестись негативно, если считаешь, что это как-то может повредить твоим продажам. А клиентов сейчас больше волнует, что вчера единственный сервис (на сколько я знаю), решающий токеном, "приказал долго жить".
Я всегда за здоровую конкуренцию) Это двигатель прогресса.
Сервис не единственный, есть альтернативы. Но не такие качественные, как были.
 
  • Спасибо
Реакции: volody00

samsonnn

Client
Регистрация
02.06.2015
Сообщения
1 761
Благодарностей
1 432
Баллы
113
//открываем в новой вкладке instance.NewTab("1"); instance.ActiveTab.Navigate(linkBlob); instance.ActiveTab.WaitDownloading(); Thread.Sleep(1000); //сохраняем на пк Bitmap b = new Bitmap(instance.ActiveTab.FindElementByXPath("//img", 0).DrawAsBitmap(true)); b.Save(project.Directory + @"\1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); b.Dispose(); //считываем с пк byte[] massByte = File.ReadAllBytes(project.Directory + @"\1.jpg"); string base64 = Convert.ToBase64String(massByte); return base64;
серьезно? зачем такие сложности? почему сразу картинку в память не выгружаете?
 
  • Спасибо
Реакции: Roman*

southside

Client
Регистрация
20.04.2019
Сообщения
205
Благодарностей
259
Баллы
63
Да я же не выложил полностью готовое решение, это скорее заготовка. Не думаю, что из-за этого будут проблемы. Тут скорее ты мог бы отнестись негативно, если считаешь, что это как-то может повредить твоим продажам. А клиентов сейчас больше волнует, что вчера единственный сервис (на сколько я знаю), решающий токеном, "приказал долго жить".
На них, кстати, майкрософт в суд подали (домен они же отжали), если кому интересно, можно ознакомиться, там очень интересное содержание
Короче все кто продает решения капчи Arkose - преступники :(
 
  • Спасибо
Реакции: Roman*

samsonnn

Client
Регистрация
02.06.2015
Сообщения
1 761
Благодарностей
1 432
Баллы
113
  • Спасибо
Реакции: southside

radv

Client
Регистрация
11.05.2015
Сообщения
3 785
Благодарностей
1 949
Баллы
113

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93

southside

Client
Регистрация
20.04.2019
Сообщения
205
Благодарностей
259
Баллы
63
По мнению майкрософта :-)
"The Defendants are members of a criminal enterprise (hereinafter the “Fraudulent
Enterprise” or “Enterprise”) that uses lies and deception to breach Microsoft’s CAPTCHA and
other security measures" и тд
Это из пдфки суда. Вообще интересно, не помню, чтобы когда-либо сервисы капчи трогали таким вот образом
 

samsonnn

Client
Регистрация
02.06.2015
Сообщения
1 761
Благодарностей
1 432
Баллы
113

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93
гугл не кто не отменял, и чат гпт тоже, я гуглил искал, проверял, а тебе готовое выдать? нет.
Я лишь привел пример, сам то я только с трафиком работаю. Меня всё устраивает, но возможно другим было бы полезно. Жаль, что вы не хотите внести свою лепту в эту статью, раз уж сами предложили улучшение. На этой ноте тему закроем, может кто-то другой напишет
 

Porosenok

Client
Регистрация
26.09.2010
Сообщения
1 280
Благодарностей
96
Баллы
48
Делал для себя такое же решение под рекапчу и фанкапчу. Не знал что это что-то настолько сложное и интересное что достойно написания статьи в конкурсе
 

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93
Делал для себя такое же решение под рекапчу и фанкапчу. Не знал что это что-то настолько сложное и интересное что достойно написания статьи в конкурсе
Жаль, что чел с 13 летним опытом за всё это время не нашёл время и силы порадовать нас своими СЛОЖНЫМИ И ИНТЕРЕСНЫМИ материалами на конкурсе статей. Будем надеется, что к следующему конкурсу это изменится.
 
  • Спасибо
Реакции: S10n4eg и rastvl

Ysocnet

Client
Регистрация
24.09.2019
Сообщения
106
Благодарностей
58
Баллы
28
Есть несколько способов решения капч с помощью сервисов:
  • Токеном
  • Прокликиванием картинок
  • Через расширение
В этой статье мы с вами рассмотрим второй способ на примере FunCaptcha, т.к. именно с ней я наиболее плотно работал последние пару месяцев. Освоив принципы, изложенные в статье, вы также сможете написать решение для hcaptcha, recaptcha или любой другой капчи, которую можно решить кликами.

Что нам с вами нужно для успешного решения капчи:
  • Уметь читать документацию API сервисов для решения капч, составлять запросы и обрабатывать ответы
  • Уметь получать задание и картинку со страницы
Важно: я не буду тут выкладывать полностью готовое решение. Отладка и доведение до ума уже ложится на ваши плечи, если оно вам действительно нужно.

Разбираемся с составлением запросов

Весь процесс будем рассматривать на примере Capmonster.cloud. Освоив работу с ним, вы сможете работать и с любым другим сервисом по решению капч.

Первым делом заходим на страницу с описанием API. Для этого достаточно вбить в поисковик «API название сервиса». Для capmonster.cloud - https://zennolab.atlassian.net/wiki/spaces/APIS/pages/589825

По сути нам с вами нужно сделать всего два запроса:
  • Создать задачу
  • Получить результат решения
Почти во всех сервисах документация условно поделена на две части: как в принципе создавать запросы и что нужно заполнять при решении конкретной капчи. Т.е. нет одной страницы, где пошагово будет описано, как и что делать.

Посмотреть вложение 115203

Перейдем на страницу создания задачи и посмотрим, что там есть.

Посмотреть вложение 115204

1 – урл, куда надо отправлять запрос
2 – тип данных. Почти всегда это json
3 – какие параметры надо передавать.
4 – тип параметра. Если это string, то заключаем в двойные кавычки. Если написано «объект», значит внутрь него будут вложены другие параметры
5 – обязательный или нет. Если не передать обязательный параметр, мы получим ошибку.
6 – описание

Давайте сразу перейдем в PM и заполним кубик POST запроса
Посмотреть вложение 115205
Посмотреть вложение 115206

1-урл (https://api.capmonster.cloud/createTask)
2-тип данных. Т.к. у нас в документации было прописано json, мы прописываем application/json
3 – тело запроса в формате JSON. JSON – это текстовый формат обмена данными. Заполняется в фигурных скобках в формате {“ключ”:”значение”}. Обратите внимание, что task у нас объект, поэтому в качестве значения выступает другой объект (поэтому я поставил фигурные скобки, но пока не заполнил содержимое). Также обратите внимание на значение ключа clientkey – оно будет подставлено из переменной cfg_apikey
4 – переменная, куда ляжет ответ от сервиса capmonster.cloud.

Чтобы заполнить task, нам надо перейти на страницу с нужной капчей. В нашем случае это FunCaptcha. Но сначала небольшое отступление.

Recaptcha, hCaptcha, FunCaptcha можно решить двумя способами – токеном и кликами. В первом случае решение идет токеном, т.е. вам будет прислан ответ в «текстовом» виде, который вы самостоятельно должны вставить на страницу и отправить сайту. Во втором случае вы высылаете сервису картинку, а он говорит, куда вам надо кликнуть. Мы работаем с вариантом №2.

Название нужного нам способа ComplexImageTask - https://zennolab.atlassian.net/wiki/spaces/APIS/pages/2293497857/ComplexImageTask+Funcaptcha+Funcaptcha
Посмотреть вложение 115207

Обратите внимание на параметры imageUrls и imagesBase64. В данном случае нам на выбор дается один из двух вариантов: либо мы высылаем массив урл (которые ведут на изображения), либо сами картинки в формате base64. Мы будем пользоваться вариантом №2. Давайте перейдем в PM и заполним содержимое нашего task
C#:
{
  "clientKey": "{-Variable.cfg_apiKey-}",
  "task": {
    "type": "ComplexImageTask",
    "class": "funcaptcha",
    "imageUrls": [
      "{-Variable.images-}"
    ],
    "metadata": {
      "Task": "{-Variable.issue-}"
    }
  }
}
Давайте сразу создадим и кубик для получения результата:
Посмотреть вложение 115208


И не забудьте создать переменные, которые мы использовали в кубиках (нажимаем на плюсик): cfg_apiKey, images, issue, taskId.

Добываем задание и картинку

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

В трафике отображаются все запросы, посылаемые браузером. Мы можем вытаскивать оттуда любые данные, в том числе и картинки. Давайте сначала потренируемся, а потом займемся уже капчей. Будем вытаскивать вот эту картинку и заголовок с сайта nashcsgo.com
Посмотреть вложение 115209


Включаем окно трафика

Посмотреть вложение 115210

Прописываем в кубике c# (выполняем это 1 раз перед началом работы с сайтом, чтобы не было проблем в zp)
C#:
instance.UseTrafficMonitoring = true;
Очищаем трафик, открываем devTools и вкладку NetWork, чтобы запросы также отображались и там тоже (помимо окна трафика) и переходим на сайт
Посмотреть вложение 115211
Выбираем img, чтобы отображались только картинки(1), жмём по любой картинке(2), выбираем preview, чтобы видеть сами картинки (3) и находим ту, что нам нужна.
Посмотреть вложение 115212

Жмём на Headers(1) и забираем урл картинки (2)
Посмотреть вложение 115213

Теперь отыщем наш заголовок. Для этого прям там же жмем ctrl+f и в появившемся окне вводим наш заголовок. Жмем enter
Посмотреть вложение 115214

Жмём на найденное совпадение (3). Жёлтым подчеркнут наш заголовок. Жмём на headers, чтобы забрать урл.

Теперь займёмся перебором всего трафика. Наша задача – выцепить два урл, которые мы с вами нашли и достать тело (т.е. то, что во вкладке response).

Сначала создайте две переменные - img_base64 для картинки и issue

переходим в кубик c#.
C#:
var traffic = instance.ActiveTab.GetTraffic();
project.SendInfoToLog($"количество запросов в трафике - {traffic.Count().ToString()}");
foreach (var t in traffic)
{
    //если в урл содержится images/skinsmin.jpg (картинка)
    if(t.Url.Contains("images/skinsmin.jpg"))
    {
        project.SendInfoToLog("нашли картинку");
   
        //дожидаемся полной прогрузки тела запроса
        t.WaitResponse(30, 2);
   
        //сохраняем в переменную "images" в формате base64 (создайте переменную вручную!)
        var imageBytes = t.ResponseBody;
        project.Variables["images"].Value = Convert.ToBase64String(imageBytes);
   
        //сохраняем на пк (этого делать не нужно, это просто для самопроверки)
        File.WriteAllBytes(project.Directory + @"\1.jpg", imageBytes);
   
    }

    //если урл равен https://nashcsgo.com/
    if(t.Url == "https://nashcsgo.com/")
    {
        project.SendInfoToLog("нашли заголовок");
        t.WaitResponse(30, 2);
   
        //сохраняем в переменную "issue" тело запроса
        var imageBytes = t.ResponseBody;
        project.Variables["issue"].Value = Encoding.UTF8.GetString(imageBytes, 0, imageBytes.Length);
    }
}

//проверка на пустоту и выход по ошибке
if(string.IsNullOrWhiteSpace(project.Variables["images"].Value)) throw new Exception("картинка не найдена");
if(string.IsNullOrWhiteSpace(project.Variables["issue"].Value)) throw new Exception("заголовок не найден");
Если вы всё сделали верно, то в переменной images у вас картинка в формате base64, в issue исходный код страницы (я уж не стал вычленять оттуда именно заголовок) и в папке проекта изображение 1.jpg (сохранил я её чисто для самопроверки, в рабочем проекте вы эту строчку убираете).

Хотел бы заострить ваше внимание на одном важном моменте – после того, как вы выполните этот код трафик будет очищен. Нет, визуально вы всё ещё будете его видеть, но если выполнить код ещё раз – то он уже не сработает. Важно держать это в голове.

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

Так, если что-то непонятно, лучше проделайте всё сами, ну а мы перейдем уже к капче. Тут будем делать тоже самое (почти). Выставляем в настройках английский профиль, т.к. нам нужно отсылать задание именно на английском языке
Посмотреть вложение 115215


Перейдем на github.com и начнем процесс регистрации, пока не дойдем до капчи. Откройте также chromeDevTools и вкладку Network, чтобы мы могли отыскать картинку.
Посмотреть вложение 115218

Что мы здесь видим? Во-первых, нам отдаётся изображение целиком, так что никаких дополнительным манипуляций не нужно. Во-вторых, нам подходят два урл: rtig/image и blob. Нам нужен rtig/image. Почему? Потому что blob не отображается в мониторе трафика. Почему? Вопрос не ко мне.
Посмотреть вложение 115219

C#:
var traffic = instance.ActiveTab.GetTraffic();
project.Variables["images"].Value = "";
project.SendInfoToLog($"количество запросов в трафике - {traffic.Count().ToString()}");
foreach (var t in traffic)
{
    if(t.Url.Contains("rtig/image"))
    {
        project.SendInfoToLog("нашли картинку");
   
        t.WaitResponse(30, 2);
   
        var imageBytes = t.ResponseBody;
        project.Variables["images"].Value = Convert.ToBase64String(imageBytes);
   
        File.WriteAllBytes(project.Directory + @"\1.jpg", imageBytes);
   
    }
}

//проверка на пустоту и выход по ошибке
if(string.IsNullOrWhiteSpace(project.Variables["images"].Value)) throw new Exception("картинка не найдена");
С заголовком немного сложнее. Он есть в трафике, но я не смог его однозначно идентифицировать. Поэтому мы просто заберем его со страницы.
C#:
//находим элемент с заданием
var issue = instance.ActiveTab.FindElementByXPath("//*[@id='root']//h2/span", 0);
if(issue.IsVoid) throw new Exception(«не нашли задание на странице»);

//убираем <strong>, </strong>, (1 of *) и пробелы и сохр в переменную issue
string noStrong = issue.InnerHtml.Replace("<strong>", "").Replace("</strong>","").Trim();
project.Variables["issue"].Value = noStrong.Replace(Regex.Match(noStrong, @”\(.*\)”).Value, @"").Trim();
project.SendInfoToLog("получили задание – " + project.Variables["issue"].Value);
А можно ли было картинку тоже вытащить из кода страницы, не прибегая к работе с трафиком? Можно, но некоторую сложность составляет то, что тут у нас blob изображения. Раньше я не знал как это сделать, но во время написания этой статьи наткнулся на способ. Сделать можно так (может кто предложит в комментариях решение без сохранения картинки на пк?)
C#:
//достаем наш урл
var imgBlob = instance.ActiveTab.FindElementByXPath("//img[@aria-live='assertive']", 0);
if(imgBlob.IsVoid) throw new Exception("не нашли картинку");
string styleBlob = imgBlob.GetAttribute("style");
string linkBlob = Regex.Match(styleBlob, @"blob:.*(?="")").Value;
if(string.IsNullOrWhiteSpace(linkBlob)) throw new Exception("не смогли достать урл картинки регуляркой");

//открываем в новой вкладке
instance.NewTab("1");
instance.ActiveTab.Navigate(linkBlob);
instance.ActiveTab.WaitDownloading();
Thread.Sleep(1000);

//сохраняем на пк
Bitmap b = new Bitmap(instance.ActiveTab.FindElementByXPath("//img", 0).DrawAsBitmap(true));
b.Save(project.Directory + @"\1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
b.Dispose();

//считываем с пк
byte[] massByte = File.ReadAllBytes(project.Directory + @"\1.jpg");
string base64 = Convert.ToBase64String(massByte);
return base64;
Отправка на распознование и получение результата

Зайдите в личный кабинет capmonster.cloud, скопируйте ключ и вставьте в переменную cfg_apikey
Посмотреть вложение 115220

Теперь у нас есть всё необходимое для отправки на сервис capmonster.cloud. Выполняем наш кубик create и смотрим, что нам прислали в ответ. Чтобы проверить, найдите запрос в трафике, нажмите по нему два раза мышкой и перейдите на вкладку ответ. Если там error id=0, значит всё ок
Посмотреть вложение 115221
Сделаем проверку на то, что errorId == 0. Если это не так, то выйдем по ошибке и выведем сообщение в лог. Я делаю регулярками (это неправильно, но мне так привычнее), вы можете делать как вам удобно (с помощью кубика json)
Посмотреть вложение 115222
errorId\":0



Достаем taskId из ответа и кладем в переменную taskId. Ставим паузу в 1 сек и делаем запрос на получение ответа.

(?<="taskId":)\d+

Тут вы можете получить следующие ответы:
  • Ready – капча решена
  • Processing – в процессе решения
  • ERROR_CAPTCHA_UNSOLVABLE – сервис не может решить капчу
Посмотреть вложение 115224
Нам нужно сделать обработку для всех трех вариантов (если непонятно сделайте себе на кубиках).
C#:
//проверяем на ERROR_CAPTCHA_UNSOLVABLE
string errorUnsolvable = Regex.Match(project.Variables["getResult"].Value, @"ERROR_CAPTCHA_UNSOLVABLE").Value;
if(!string.IsNullOrWhiteSpace(errorUnsolvable)) throw new Exception("ERROR_CAPTCHA_UNSOLVABLE");


//проверяем статус
string status = Regex.Match(project.Variables["getResult"].Value, @"(?<=status"":"").*?(?="")").Value;
if(string.IsNullOrEmpty(status)) throw new Exception("не смогли извлечь status из ответа - " + project.Variables["getResult"].Value);

switch(status)
{
    //получили processing
    case "processing":
        project.SendInfoToLog("капча в процессе решения");
        project.Variables["statusSolution"].Value = "processing";
        break;
    //получили ready
    case "ready":
        project.SendInfoToLog("капча решена");
        project.Variables["statusSolution"].Value = "ready";
        break;
    default:
        throw new Exception("не смогли определить статус (не processing и не ready) - " + status);
}
Посмотреть вложение 115226
Сразу скажу, что ERROR_CAPTCHA_UNSOLVABLE не так, чтобы редкое явление. Тяжелые задания сервисы вообще не решают и не будут решать. Легкими заданиями считаются те, где нужно повернуть что-то в направлении руки и самих вариантов не больше 5. Ещё недавно это были животные и capmonster.cloud успешно их решал, но сейчас, как видим, картинки обновили и capmonster.cloud с ними не справляется. Возможно, на момент выхода статьи нейросеть уже будет обучена и сможет решать такие задания.

Чтобы попадались легкие задания используйте хорошие прокси и движок хромиум.

Так что далее вам придется поверить мне на слово. Вам придет ответ такого вида:
{"solution":{"answer":[false,false,false,false,false,true],"metadata":null},"cost":0.00015,"status":"ready","errorId":0,"errorCode":null,"errorDescription":null}
Там где true – это нужная нам картинка. Соответственно, нам надо с вами посчитать, какая она. После этого жмем по стрелке нужное количество раз и отправляем ответ.
C#:
//узнаем сколько раз надо кликнуть по стрелке
project.Json.FromString(project.Variables["getResult"].Value);
var otv = project.Json.solution.answer.ToString().Split(',');
string countClickCapmonster = Convert.ToString(otv.Length - 1);
if(string.IsNullOrWhiteSpace(countClickCapmonster)) throw new Exception("не смогли получить сколько раз надо кликать по стрелке вправо CapmonsterCloud");
project.SendInfoToLog($"нужно кликнуть {countClickCapmonster} раз");

//находим стрелку вправо
HtmlElement rightArrow = instance.ActiveTab.FindElementByXPath("(//a/*/*[name()='circle']/following-sibling::*)[last()]|(//a/*/*[name()='circle'])[last()]", 0);
if(rightArrow.IsVoid) throw new Exception("не найдена стрелка для переключения картинок");

//щелкаем нужное количество раз
for(int i=0;i<Convert.ToInt32(countClickCapmonster);i++)
{
    rightArrow.Click();
    Thread.Sleep(1000);
}

//жмем submit
var buttonSubmit = instance.ActiveTab.FindElementByXPath("//button[text()='Submit']", 0);
if(buttonSubmit.IsVoid) throw new Exception("не найдена кнопка submit");
buttonSubmit.Click();
Thread.Sleep(3000);
project.SendInfoToLog("нажали на нужное изображение");
Теперь надо определить есть ли ещё задания. Если да, то снова ищем картинку в трафике и отправляем на сервис. Если нет, тогда определяем, успешно ли мы решили капчу и действуем исходя из этого (если неудачно, можем попытаться снова или можно выйти по ошибке)
//если стрелка вправо есть, значит задания ещё есть
HtmlElement rightArrow = instance.ActiveTab.FindElementByXPath("(//a/*/*[name()='circle']/following-sibling::*)[last()]|(//a/*/*[name()='circle'])[last()]", 0);
if(!rightArrow.IsVoid)
{
    project.SendInfoToLog("задания ещё есть, продолжаем решать");
    project.Variables["status"].Value = "process";
    return "";
}

//решено неверно
HtmlElement notRight = instance.ActiveTab.FindElementByXPath("//h2[contains(text(), 'That was not quite right.')]", 0);
if(!notRight.IsVoid)
{
    project.SendInfoToLog("капча была решена неверно");
    project.Variables["status"].Value = "notRight";
    return "";
}

//галочка
var galka = instance.ActiveTab.FindElementByXPath("//img[contains(@src, 'thub-api.arkoselabs.com/cdn/fc/assets/style-manager/assets')]", 0);
if(!galka.IsVoid)
{
    project.SendInfoToLog("капча решена верно");
    project.Variables["status"].Value = "ready";
    return "";
}

//если не смогли опрелелить
project.Variables["status"].Value = "unknown";
Теперь надо определить есть ли ещё задания. Если да, то снова ищем картинку в трафике и отправляем на сервис. Если нет, тогда определяем, успешно ли мы решили капчу и действуем исходя из этого (если неудачно, можем попытаться снова или можно выйти по ошибке)
C#:
//если стрелка вправо есть, значит задания ещё есть
HtmlElement rightArrow = instance.ActiveTab.FindElementByXPath("(//a/*/*[name()='circle']/following-sibling::*)[last()]|(//a/*/*[name()='circle'])[last()]", 0);
if(!rightArrow.IsVoid)
{
    project.SendInfoToLog("задания ещё есть, продолжаем решать");
    project.Variables["status"].Value = "process";
    return "";
}

//решено неверно
HtmlElement notRight = instance.ActiveTab.FindElementByXPath("//h2[contains(text(), 'That was not quite right.')]", 0);
if(!notRight.IsVoid)
{
    project.SendInfoToLog("капча была решена неверно");
    project.Variables["status"].Value = "notRight";
    return "";
}

//галочка
var galka = instance.ActiveTab.FindElementByXPath("//img[contains(@src, 'thub-api.arkoselabs.com/cdn/fc/assets/style-manager/assets')]", 0);
if(!galka.IsVoid)
{
    project.SendInfoToLog("капча решена верно");
    project.Variables["status"].Value = "ready";
    return "";
}

//если не смогли опрелелить
project.Variables["status"].Value = "unknown";
Задания со стрелками попадаются чаще всего. Но также есть ещё задания, где надо выбрать одну из 6 картинок. Все делается аналогично, только надо будет кликать по нужному изображению, а не по стрелке. Эту часть я вам оставляю в качестве самостоятельной работы.

Заработок на решении капч
Посмотреть вложение 115232

5 октября я на форуме разместил тему о продаже плагина для решения FunCaptcha. За прошедшее время было 23 продажи на общую сумму 71 000 руб + было пара индивидуальных заказов. Размещался я только на этом форуме. Вроде бы неплохо, но есть несколько нюансов:
  • Не считая пары человек, взявших плагин на месяц, последняя продажа с форума была 6 ноября.
  • 15 продаж для меня сделал партнер, т.е. мне просто повезло. Человек предложил приводить клиентов за часть дохода, и я согласился. Если бы не он, у меня было бы всего 8 продаж.
Помимо дохода с продажи плагина удалось получить доход с партнерок капч (что явилось для меня полной неожиданностью). Если кто не в курсе, то большинство сервисов решения капч позволяют к запросам добавлять свой идентификатор и когда пользователь решает капчу, то вам падает небольшой процент.

Я тут ни на что не рассчитывал и добавил его больше по приколу. Какого же было моё удивление, когда я в один из дней увидел у себя на балансе $30. Поначалу я даже не мог врубиться, откуда они взялись и только потом до меня дошло, что я же размещал идентификатор. Сейчас у меня на балансе $130. Не так уж и плохо с 23 клиентов.

Вот тут lord_alfred поделился своими цифрами, можете также глянуть. У capmonster.cloud также есть партнерка, но нужно написать в саппорт, чтобы вам дали доступ. Так что этот вариант также не стоит списывать со счетов.

На этом всё. Для закрепления материала также можете посмотреть видео, где мы разбираемся с Recaptcha.

Видео - https://drive.google.com/file/d/1hRhAPWack-CiD1lUza3Up7UjFshBK_Yf/view?usp=sharing
Хорошая статья. Спасибо за проделанный труд и предоставленный материал
 
  • Спасибо
Реакции: rastvl и volody00

rastvl

Client
Команда форума
Регистрация
16.01.2019
Сообщения
656
Благодарностей
1 061
Баллы
93
Что мы здесь видим? Во-первых, нам отдаётся изображение целиком, так что никаких дополнительным манипуляций не нужно
У фанкапчи это не всегда так. На самом деле бывает по /image?challenge прилетает json с немного зашифрованными данными, которые нужно обработать определенным образом, чтобы получить картинку
нам подходят два урл: rtig/image и blob. Нам нужен rtig/image. Почему? Потому что blob не отображается в мониторе трафика. Почему? Вопрос не ко мне.
Тут согласен. Вопрос к разработчикам зенки) В трафике запрос виден, в "Protocol Monitor"(ctrl + F на странице) тоже, причём ответ там сразу в base64) Видимо, не ко всем фреймам ЗП цепляется. Может в восьмёрке лучше будет(Я не знаю)

Статья полезная, спасибо:dh::ay:. Но допускаю, новичкам с видео было бы понятнее)
 
  • Спасибо
Реакции: volody00

rastvl

Client
Команда форума
Регистрация
16.01.2019
Сообщения
656
Благодарностей
1 061
Баллы
93
Не знал что это что-то настолько сложное и интересное
А автор, как минимум, из-за допуска к конкурсу получит халявные обновы, потому что знал) И кто из вас тут больше шарит?)
 
  • Спасибо
Реакции: Alexmd

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93
У фанкапчи это не всегда так. На самом деле бывает по /image?challenge прилетает json с немного зашифрованными данными, которые нужно обработать определенным образом, чтобы получить картинку
Видел такое. Но на самом деле не обязательно эту картинку расшифровывать. Если такое встречается, картинку можно вытащить из урл начинающегося с blob. Если такого урл в трафике нет, то это сложное задание и сервисы его не решают (нет смысла доставать картинку).

К слову, если знаешь сервисы, решающие токеном Твиттер, напиши в ЛС (если не сложно), а то найти не получается. Спасибо
 

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 786
Благодарностей
2 450
Баллы
113
Сделать можно так (может кто предложит в комментариях решение без сохранения картинки на пк?)
C#:
//достаем наш урл
var imgBlob = instance.ActiveTab.FindElementByXPath("//img[@aria-live='assertive']", 0);
if(imgBlob.IsVoid) throw new Exception("не нашли картинку");
string styleBlob = imgBlob.GetAttribute("style");
string linkBlob = Regex.Match(styleBlob, @"blob:.*(?="")").Value;
if(string.IsNullOrWhiteSpace(linkBlob)) throw new Exception("не смогли достать урл картинки регуляркой");

//открываем в новой вкладке
instance.NewTab("1");
instance.ActiveTab.Navigate(linkBlob);
instance.ActiveTab.WaitDownloading();
Thread.Sleep(1000);

//сохраняем на пк
Bitmap b = new Bitmap(instance.ActiveTab.FindElementByXPath("//img", 0).DrawAsBitmap(true));
b.Save(project.Directory + @"\1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
b.Dispose();

//считываем с пк
byte[] massByte = File.ReadAllBytes(project.Directory + @"\1.jpg");
string base64 = Convert.ToBase64String(massByte);
return base64;
Попробуй, может быть такое преобразование будет удобнее (без сохранения на диск):
C#:
string base64 ="";

using (var ms = new MemoryStream()) {   
    using (var b = new Bitmap(instance.ActiveTab.FindElementByXPath("//img", 0).DrawAsBitmap(true))) { 
        b.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
// b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        base64 = Convert.ToBase64String(ms.GetBuffer());
    }
}
 

FastSpace

Client
Read only
Регистрация
05.04.2018
Сообщения
665
Благодарностей
240
Баллы
43
У фанкапчи это не всегда так. На самом деле бывает по /image?challenge прилетает json с немного зашифрованными данными, которые нужно обработать определенным образом, чтобы получить картинку
У FunCaptha 6 видов каптч (известных мне), то что описал автор подойдет только к 3.
Например есть вид каптчи, где картинку таким способом не поймаешь, она спрятана в свойстве CSS.

Еще есть такой прикол (на амазон видел) тебе пикча приходит 450x300, а реальный размер ее в CSS 300x300. Ты пошлешь 450x300 тебе придут координаты которые не сопадут с 300x300
 
Последнее редактирование:

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 786
Благодарностей
2 450
Баллы
113
У FunCaptha 6 видов каптч (известных мне), то что описал автор подойдет только к 3.
Например есть вид каптчи, где картинку таким способом не поймаешь, она спрятана в свойстве CSS.
Разве автор где-то указал, что он подготовил комплексное решение, которое должно решать все виды FunCaptha?
С какими встречался и знает как с ними работать - об этом написал.
Что не знает - кто-то другой напишет в будущем.
 
  • Спасибо
Реакции: Petr_G

FastSpace

Client
Read only
Регистрация
05.04.2018
Сообщения
665
Благодарностей
240
Баллы
43
Разве автор где-то указал, что он подготовил комплексное решение, которое должно решать все виды FunCaptha?
С какими встречался и знает как с ними работать - об этом написал.
Что не знает - кто-то другой напишет в будущем.
Я это говорил ежику, а не автору.
 

KiryaPerseus

Client
Регистрация
17.10.2017
Сообщения
160
Благодарностей
62
Баллы
28
Круто! Спасибо за статью, видел вашу тему с продажей плагина, недавно сам сел читать документацию Capmonstecloud API
И пилить решение фанкапчи, статья с кликиками помогла!)
 
  • Спасибо
Реакции: volody00 и n0n3mi1y

bagzik

Client
Регистрация
16.07.2013
Сообщения
6
Благодарностей
5
Баллы
3
Спасибо большое за статью! Интересно было потестить решение капчи на гитхабе, а то я как-то пробовал написать авторегер аккаунтов github, но не смог побороть модуль с funcaptcha.

К сожалению и при тестировании этого шаблона не удается распознать капчпу((

Такая ошибка: {"errorId":1,"errorCode":"ERROR_CAPTCHA_UNSOLVABLE","errorDescription":"This type of captchas is not supported by the service or the image does not contain an answer, perhaps it is too noisy. It could also mean that the image is corrupted or was incorrectly rendered. "}
 

volody00

Client
Регистрация
06.09.2016
Сообщения
917
Благодарностей
950
Баллы
93
Спасибо большое за статью! Интересно было потестить решение капчи на гитхабе, а то я как-то пробовал написать авторегер аккаунтов github, но не смог побороть модуль с funcaptcha.

К сожалению и при тестировании этого шаблона не удается распознать капчпу((

Такая ошибка: {"errorId":1,"errorCode":"ERROR_CAPTCHA_UNSOLVABLE","errorDescription":"This type of captchas is not supported by the service or the image does not contain an answer, perhaps it is too noisy. It could also mean that the image is corrupted or was incorrectly rendered. "}
Ждите, пока capmonster.cloud переобучит свою нейросеть под новые задания
 
  • Спасибо
Реакции: ZennoLab Team

softweri

Client
Регистрация
03.03.2016
Сообщения
108
Благодарностей
17
Баллы
18
А кто поделится таким на hCaptcha
 

softweri

Client
Регистрация
03.03.2016
Сообщения
108
Благодарностей
17
Баллы
18

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)