Решение капчи с помощью сервиса Anti Capcha можно условно разделить на 3 этапа:
- Получение изображения в Base64
- Создание задачи на решение
- Получение результата решения
Накидаем простенький интерфейс - форма, реквизит вида картинка, реквизит поле ввода, 2 команды;
- GetImage - получение капчи, помещение в хранилище, вывод на форму
- SolveCapcha - создание задачи на решение и вывод результа
Фича делалась для англоязычного проекта поэтому код будет на английском.
Получаем картинку с веб ресурса get запросом, помещаем во временное хранилище и выводим на форму:
&AtClient
Procedure GetImage(Command)
ImageBinary = GetImageAtServer();
Image = PutToTempStorage(ImageBinary,UUID);
EndProcedure
&AtServer
Function GetImageAtServer()
Headers = New Map;
Headers.Insert("Host", "www.adultwork.com");
Headers.Insert("Connection", "keep-alive");
Headers.Insert("Upgrade-Insecure-Requests", "1");
Headers.Insert("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
Headers.Insert("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36");
Headers.Insert("Accept-Language", "en-US,en;q=0.8,ru;q=0.6");
Headers.Insert("Cookie", "C=149; ReferralID=0;CameViaEntryPage=CountryID=149&GMTOffset=%2D180&HitID=1234660132&Time=12%2F09%2F2017+20%3A37%3A31");
Connection = New HTTPConnection("www.adultwork.com",,,,,, New OpenSSLSecureConnection);
Request = New HTTPRequest("imgTuring.asp", Headers);
Response = Connection.CallHTTPMethod("GET", Request);
ImageBinary = Response.GetBodyAsBinaryData();
Return ImageBinary;
EndFunction
Далее приступаем к решению. Заводим клиентский ключ с сайта, получаем картинку и передаем данные в следующую функцию.
&AtClient
Procedure SolveCaptcha(Command)
ClientKey = "ххххххххххххххххххххххххх"; //put your key here
ImageBinary = GetFromTempStorage(Image);
Captcha = SolveCaptchaAtServer(ImageBinary,ClientKey);
EndProcedure
Создаем соединение, заполняем заголовки запроса и создаем задачу на решение. Если задача создана успешно, получаем результат решения. Т.к капчу решают сотрудники сервиса, то нужно некоторое время на ее решение. Методом подбора было установлено, что капча решается в среднем за 10 секунд. Делаем задержку и получаем результат решения.
&AtServer
Function SolveCaptchaAtServer(ImageBinary,ClientKey)
Connection = New HTTPConnection("api.anti-captcha.com");
Headers = New Map;
Headers.Insert("Host", "api.anti-captcha.com");
Headers.Insert("Connection", "keep-alive");
Headers.Insert("Content-Type", "multipart/form-data");
TaskResult = CreateTask(Connection,Headers,ClientKey,ImageBinary);
If TaskResult.errorId = 0 Then
Delay(10);
TaskResultBody = GetTaskResultBody(Connection,Headers,ClientKey,TaskResult.taskId);
If TaskResultBody.errorId = 0 Then
Return TaskResultBody.solution.text;
Else
Message("Result error");
Endif;
Else
Message("Failed to create task.");
EndIF;
EndFunction
&AtServer
Procedure Delay(Seconds)
TimeOut = CurrentDate() + Seconds;
While CurrentDate() <= TimeOut Do
//TODO: waiting
EndDo;
EndProcedure
Для создания задачи необходимо перевести картинку в Base64 и создать текст POST запроса. В ответе мы получим код ошибки (если ошибки нет код - 0) и id созданной задачи.
&AtServer
Function CreateTask(Connection,Headers,ClientKey,ImageBinary)
Base64Img = Base64String(ImageBinary);
JSONBody = GetTaskBody(Base64Img,ClientKey);
Request = New HTTPRequest("/createTask", Headers);
Request.SetBodyFromString(JSONBody);
Response = Connection.CallHTTPMethod("POST", Request);
ResultJson = Response.GetBodyAsString();
ReadJson = New JSONReader;
ReadJson.SetString(ResultJson);
Return ReadJSON(ReadJson);
EndFunction
&AtServer
Function GetTaskBody(Base64Img,ClientKey)
WriteJson = New JSONWriter;
WriteJson.SetString();
JsonBody = New Structure;
JsonBody.Insert("clientKey",ClientKey);
JsonTask = New Structure;
JsonTask.Insert("type","ImageToTextTask");
JsonTask.Insert("body",Base64Img);
JsonTask.Insert("phrase",False);
JsonTask.Insert("case",False);
JsonTask.Insert("numeric",False);
JsonTask.Insert("math",0);
JsonTask.Insert("minLength",0);
JsonTask.Insert("maxLength",0);
JsonBody.Insert("task",JsonTask);
WriteJSON(WriteJson,JsonBody);
Return WriteJson.Close();
EndFunction
Для получения результата решения нужно отправить POST запрос с id задачи и пользовательским ключом.
&AtServer
Function GetTaskResultBody(Connection,Headers,ClientKey,TaskId)
WriteJson = New JSONWriter;
WriteJson.SetString();
JsonBody = New Structure;
JsonBody.Insert("clientKey",ClientKey);
JsonBody.Insert("taskId",Format(TaskId,"NG="));
WriteJSON(WriteJson,JsonBody);
SerializenStr = WriteJson.Close();
Request = New HTTPRequest("/getTaskResult", Headers);
Request.SetBodyFromString(SerializenStr);
Response = Connection.CallHTTPMethod("POST", Request);
ResultJson = Response.GetBodyAsString();
ReadJson = New JSONReader;
ReadJson.SetString(ResultJson);
Return ReadJSON(ReadJson);
EndFunction
Таким образом можно логиниться в системе, получать куки и использовать эти данные для авторизации.
Спасибо за внимание, всем удачи!