- Токеном
- Прокликиванием картинок
- Через расширение
Что нам с вами нужно для успешного решения капчи:
- Уметь читать документацию API сервисов для решения капч, составлять запросы и обрабатывать ответы
- Уметь получать задание и картинку со страницы
Разбираемся с составлением запросов
Весь процесс будем рассматривать на примере Capmonster.cloud. Освоив работу с ним, вы сможете работать и с любым другим сервисом по решению капч.
Первым делом заходим на страницу с описанием API. Для этого достаточно вбить в поисковик «API название сервиса». Для capmonster.cloud - https://zennolab.atlassian.net/wiki/spaces/APIS/pages/589825
По сути нам с вами нужно сделать всего два запроса:
- Создать задачу
- Получить результат решения
Перейдем на страницу создания задачи и посмотрим, что там есть.
1 – урл, куда надо отправлять запрос
2 – тип данных. Почти всегда это json
3 – какие параметры надо передавать.
4 – тип параметра. Если это string, то заключаем в двойные кавычки. Если написано «объект», значит внутрь него будут вложены другие параметры
5 – обязательный или нет. Если не передать обязательный параметр, мы получим ошибку.
6 – описание
Давайте сразу перейдем в PM и заполним кубик POST запроса
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
Обратите внимание на параметры imageUrls и imagesBase64. В данном случае нам на выбор дается один из двух вариантов: либо мы высылаем массив урл (которые ведут на изображения), либо сами картинки в формате base64. Мы будем пользоваться вариантом №2. Давайте перейдем в PM и заполним содержимое нашего task
C#:
{
"clientKey": "{-Variable.cfg_apiKey-}",
"task": {
"type": "ComplexImageTask",
"class": "funcaptcha",
"imageUrls": [
"{-Variable.images-}"
],
"metadata": {
"Task": "{-Variable.issue-}"
}
}
}
И не забудьте создать переменные, которые мы использовали в кубиках (нажимаем на плюсик): cfg_apiKey, images, issue, taskId.
Добываем задание и картинку
Достать эти данные можно двумя способами: через трафик и через содержимое страницы. Скорее всего вы будете работать именно с трафиком, но поначалу может быть сложновато, если раньше вы этого не делали.
В трафике отображаются все запросы, посылаемые браузером. Мы можем вытаскивать оттуда любые данные, в том числе и картинки. Давайте сначала потренируемся, а потом займемся уже капчей. Будем вытаскивать вот эту картинку и заголовок с сайта nashcsgo.com
Включаем окно трафика
Прописываем в кубике c# (выполняем это 1 раз перед началом работы с сайтом, чтобы не было проблем в zp)
C#:
instance.UseTrafficMonitoring = true;
Выбираем img, чтобы отображались только картинки(1), жмём по любой картинке(2), выбираем preview, чтобы видеть сами картинки (3) и находим ту, что нам нужна.
Жмём на Headers(1) и забираем урл картинки (2)
Теперь отыщем наш заголовок. Для этого прям там же жмем ctrl+f и в появившемся окне вводим наш заголовок. Жмем enter
Жмём на найденное совпадение (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("заголовок не найден");
Хотел бы заострить ваше внимание на одном важном моменте – после того, как вы выполните этот код трафик будет очищен. Нет, визуально вы всё ещё будете его видеть, но если выполнить код ещё раз – то он уже не сработает. Важно держать это в голове.
Например, вы зашли на страницу с капчей. Запускаете код, что-то не работает, вы правите и снова запускаете – вообще всё перестает работать. Что за фигня? Просто трафик очистился. Вам нужно заново дойти до страницы с капчей и потом уже снова запустить свой код. Обход для этого есть, но там возникают другие проблемы и лучше просто смириться с подобным неудобством.
Так, если что-то непонятно, лучше проделайте всё сами, ну а мы перейдем уже к капче. Тут будем делать тоже самое (почти). Выставляем в настройках английский профиль, т.к. нам нужно отсылать задание именно на английском языке
Перейдем на github.com и начнем процесс регистрации, пока не дойдем до капчи. Откройте также chromeDevTools и вкладку Network, чтобы мы могли отыскать картинку.
Что мы здесь видим? Во-первых, нам отдаётся изображение целиком, так что никаких дополнительным манипуляций не нужно. Во-вторых, нам подходят два урл: rtig/image и blob. Нам нужен rtig/image. Почему? Потому что blob не отображается в мониторе трафика. Почему? Вопрос не ко мне.
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);
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
Теперь у нас есть всё необходимое для отправки на сервис capmonster.cloud. Выполняем наш кубик create и смотрим, что нам прислали в ответ. Чтобы проверить, найдите запрос в трафике, нажмите по нему два раза мышкой и перейдите на вкладку ответ. Если там error id=0, значит всё ок
Сделаем проверку на то, что errorId == 0. Если это не так, то выйдем по ошибке и выведем сообщение в лог. Я делаю регулярками (это неправильно, но мне так привычнее), вы можете делать как вам удобно (с помощью кубика json)
errorId\":0
Достаем taskId из ответа и кладем в переменную taskId. Ставим паузу в 1 сек и делаем запрос на получение ответа.
(?<="taskId":)\d+
Тут вы можете получить следующие ответы:
- Ready – капча решена
- Processing – в процессе решения
- ERROR_CAPTCHA_UNSOLVABLE – сервис не может решить капчу
Нам нужно сделать обработку для всех трех вариантов (если непонятно сделайте себе на кубиках).
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);
}
Сразу скажу, что 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";
Заработок на решении капч
5 октября я на форуме разместил тему о продаже плагина для решения FunCaptcha. За прошедшее время было 23 продажи на общую сумму 71 000 руб + было пара индивидуальных заказов. Размещался я только на этом форуме. Вроде бы неплохо, но есть несколько нюансов:
- Не считая пары человек, взявших плагин на месяц, последняя продажа с форума была 6 ноября.
- 15 продаж для меня сделал партнер, т.е. мне просто повезло. Человек предложил приводить клиентов за часть дохода, и я согласился. Если бы не он, у меня было бы всего 8 продаж.
Я тут ни на что не рассчитывал и добавил его больше по приколу. Какого же было моё удивление, когда я в один из дней увидел у себя на балансе $30. Поначалу я даже не мог врубиться, откуда они взялись и только потом до меня дошло, что я же размещал идентификатор. Сейчас у меня на балансе $130. Не так уж и плохо с 23 клиентов.
Вот тут lord_alfred поделился своими цифрами, можете также глянуть. У capmonster.cloud также есть партнерка, но нужно написать в саппорт, чтобы вам дали доступ. Так что этот вариант также не стоит списывать со счетов.
На этом всё. Для закрепления материала также можете посмотреть видео, где мы разбираемся с Recaptcha.
- Номер конкурса статей
- Двадцатый конкурс статей
Вложения
-
22 КБ Просмотры: 180
-
22,6 КБ Просмотры: 115
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование модератором: