ReCaptcha Audio
Пожалуйста, ознакомьтесь с Правилами использования материалов на данном ресурсе
Добавлено в ZennoPoster 5.9.5.1 и CapMonster 2.5.0.0.
В программе CapMonster2 есть возможность распознавать звуковую ReCaptcha старого и нового типа. В программе будет доступен модуль ZennoLab.AudioReCaptcha. Работает это так: когда на странице встречается ReCaptcha, нужно выбрать распознавание через аудиозапись и отправить её в CapMonster2.
Принцип работы:
Использование в ZennoPoster
Для отправки звуковых каптч из ZennoPoster Вы можете использовать подготовленный нами сниппет:
//Main settings
// waiting timeout
var waitTime = 1000;
// recognition attempts
var tryRecognize = 10;
// attempts to load element
var tryLoadElement = 60;
// show recognizing progress messages
var needShowMessages = false;
// need to check answer's correctness
var needToCheck = true;
// Additional variables
// tab
var tab = instance.ActiveTab;
// congratulations, you are not robot
var success = false;
// audio file
var file = string.Empty;
// file has been deleted
var fileDeleted = true;
// answer to audio captcha
var answer = string.Empty;
// ReCaptcha 1
var isRecaptcha1 = false;
// timeout exceeded
var timeout = false;
// error loading file
var fileLoadingError = false;
var usedURLs = new List<string>();
var isFirstAttempt = true;
var coincidenceReCaptcha2Index = -1;
// Searching audio button element
Action TryOpenAudioForm = () => {
for (int k = 0; k < tryLoadElement; k++)
{
var audioButton = tab.FindElementById("recaptcha-audio-button");
// if found
if (!audioButton.IsVoid)
{
// press button
audioButton.Click();
tab.WaitDownloading();
break;
}
System.Threading.Thread.Sleep(waitTime); // pause
if (k == (tryLoadElement - 1)) timeout = true;
}
System.Threading.Thread.Sleep(waitTime); // pause
};
Action OpenAudioTask= () => {
project.SendInfoToLog("Loading audio task", needShowMessages);
//checking task type in the form
var task = tab.FindElementByAttribute("div", "class", "rc-imageselect-desc-wrapper", "regexp", 0);
if (!task.IsVoid) TryOpenAudioForm(); // graphic task has been found, then loading audio
};
Action VisibleIndexReCaptchaDefinition= () => {
var recaptchaElementsGroup = tab.FindElementsByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp");
int length = recaptchaElementsGroup.Elements.Length;
if (length == 1)
{
coincidenceReCaptcha2Index = 0;
return;
}
for(int i = 0; i < length; i++)
{
var element = recaptchaElementsGroup.Elements[i];
if (!element.IsVoid)
{
int x = element.DisplacementInTabWindow.X;
int y = element.DisplacementInTabWindow.Y;
var suspectVisibleElement = tab.GetElementFromPoint(x, y).DisplacementInTabWindow;
if (x == suspectVisibleElement.X && y == suspectVisibleElement.Y && element.Width != 0 && element.Height != 0 && x != 0 && y != 0)
{
coincidenceReCaptcha2Index = i;
break;
}
}
}
};
// Identifying ReCaptcha version
Action NotRobotClick= () => {
for (int k = 0; k < tryLoadElement; k++)
{
VisibleIndexReCaptchaDefinition();
if (coincidenceReCaptcha2Index < 0) coincidenceReCaptcha2Index = 0;
// поиск кнопки "Я не робот"
HtmlElement notRobot = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
// кнопка существует
if (!notRobot.IsVoid)
{
// клик по кнопке
notRobot.Click();
System.Threading.Thread.Sleep(waitTime); // подождём немного
// если ввод каптчи не требуется
var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
if (!check.IsVoid)
{
if (check.OuterHtml.Contains("style=\"\""))
{
success = true;
timeout = false;
break;
}
}
}
// Форма существует
var loadedForm = tab.FindElementByAttribute("div", "class", "primary-controls", "regexp", 0);
if (!loadedForm.IsVoid)
break;
// checking if ReCaptcha 1 audio button exists
HtmlElement r1 = tab.FindElementById("recaptcha_switch_audio");
if (!r1.IsVoid)
{
r1.Click();
isRecaptcha1 = true;
break;
}
// подождём загрузки элементов
System.Threading.Thread.Sleep(waitTime);
if (k == (tryLoadElement - 1)) timeout = true;
}
};
// Downloading mp3 file
Action GetAudioFile= () => {
var href = String.Empty;
// getting audio task
for (int k = 0; k < tryLoadElement; k++)
{
if (isRecaptcha1)
{
var audioChallenge = tab.FindElementByAttribute("a", "id", "recaptcha_audio_download", "text", 0);
// if found, getting link to audio file
if (!audioChallenge.IsVoid)
{
href = audioChallenge.GetAttribute("href");
break;
}
else System.Threading.Thread.Sleep(waitTime);
}
else
{
if (isFirstAttempt)
{
isFirstAttempt = false;
}
else
{
var reload = tab.FindElementById("recaptcha-reload-button");
if (!reload.IsVoid)
{
reload.Click();
tab.WaitDownloading();
}
}
var audioChallenge = tab.FindElementByAttribute("a", "class", "rc-audiochallenge-tdownload-link", "regexp", 0);
// if found, getting link to audio file
if (!audioChallenge.IsVoid)
{
href = audioChallenge.GetAttribute("href");
break;
}
System.Threading.Thread.Sleep(waitTime); // waiting when form will be loaded
}
if (k == (tryLoadElement - 1)) timeout = true;
}
foreach (var usedUrl in usedURLs)
{
if (usedUrl.Contains(href))
throw new Exception("new audio file is absent");
}
usedURLs.Add(href);
project.SendInfoToLog("Downloading audio file", needShowMessages);
try
{
var proxy = instance.GetProxy();
var respType = ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.File;
var timeoutRequest = 30000;
var cookies = instance.GetCookie("google.com", true);
var userAgent = project.Profile.UserAgent;
var maxRedirectCount = 1;
var downloadPath = project.Directory + "\\audiofiles";
file = ZennoPoster.HttpGet(href, proxy, "UTF8", respType, timeoutRequest, cookies, userAgent, false, maxRedirectCount, null, downloadPath);
fileDeleted = false;
}
catch (Exception ex)
{
throw new Exception("Failed to download audio file");
}
};
Action Recognize= () => {
project.SendInfoToLog("Recognizing", needShowMessages);
try
{
if (!File.Exists(file))
{
fileLoadingError = true;
fileDeleted = true;
return;
}
var bytes = File.ReadAllBytes(file);
if (bytes.Length < 1024)
{
fileLoadingError = true;
return;
}
var hexStringBuilder = new StringBuilder(2);
for (var i = 0; i < 2; i++)
hexStringBuilder.AppendFormat("{0:x2}", bytes[i]);
var header_prefix = hexStringBuilder.ToString();
if (!header_prefix.Equals("ffe3"))
{
fileLoadingError = true;
throw new Exception("Your IP was banned!");
return;
}
string str = Convert.ToBase64String(bytes);
var rc = ZennoPoster.CaptchaRecognition("CapMonster2.dll", str, "CapMonsterModule=ZennoLab.AudioReCaptcha&ParallelMode=true");
var split = rc.Split(new [] {"-|-"}, StringSplitOptions.RemoveEmptyEntries);
if (split.Length > 0)
answer = split[0];
if (answer.Contains("133193320491090004119440")) throw new Exception("Your IP was banned!");
}
finally
{
if (File.Exists(file))
{
File.Delete(file);
fileDeleted = true;
}
}
};
Action InputAnswer= () => {
if (!String.IsNullOrEmpty(answer) && answer != "sorry")
{
project.SendInfoToLog("Inserting answer", needShowMessages);
HtmlElement audioAnswerInput = null;
// searching answer input field
if (isRecaptcha1)
{
audioAnswerInput = tab.FindElementByAttribute("input:text", "id", "recaptcha_response_field", "text", 0);
}
else
{
audioAnswerInput = tab.FindElementByAttribute("input:text", "id", "audio-response", "regexp", 0);
}
// if found
if (!audioAnswerInput.IsVoid)
{
// inserting answer
audioAnswerInput.SetValue(answer, "None", false);
}
// pause
System.Threading.Thread.Sleep(waitTime);
}
else throw new Exception("Answer not received");
};
// Verifying
Action SubmitAnswer= () => {
// searching "Verify" button
HtmlElement apply = tab.FindElementById("recaptcha-verify-button");
if (!apply.IsVoid) apply.Click();
tab.WaitDownloading();
// pause
System.Threading.Thread.Sleep(waitTime);
};
// Checking if answer is correct for ReCaptcha 2
Action Check= () => {
project.SendInfoToLog("Verifying answer", needShowMessages);
tab.WaitDownloading();
for (int k = 0; k < tryLoadElement; k++)
{
System.Threading.Thread.Sleep(waitTime);
var checkAnswer = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
// проверка исчезновения формы
var loadedForm = tab.FindElementByAttribute("div", "class", "primary-controls", "regexp", 0);
if (loadedForm.IsVoid)
{
success = true;
break;
}
else
{
int xPrimaryControlsDisplaysment = loadedForm.DisplacementInTabWindow.X;
int yPrimaryControlsDisplaysment = loadedForm.DisplacementInTabWindow.Y;
if (xPrimaryControlsDisplaysment < 0 || yPrimaryControlsDisplaysment < 0) // there are no visible recaptcha
{
success = true;
break;
}
if (checkAnswer.IsVoid)
break;
}
var recaptchas = tab.FindElementsByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp");
if (recaptchas.Count == 0)
{
success = true;
return;
}
if (!checkAnswer.IsVoid)
{
if (checkAnswer.OuterHtml.Contains("style=\"\""))
success = true;
else
success = false;
return;
}
if (k == (tryLoadElement - 1)) timeout = true;
}
};
// Checking "I'm not robot" checkbox
NotRobotClick();
if (success) return "ok";
// trying to recognize ReCaptcha
for (int i = 0; i < tryRecognize; i++)
{
if (!isRecaptcha1) OpenAudioTask();
if (timeout) break;
GetAudioFile();
if (timeout) break;
Recognize();
if (fileLoadingError)
{
fileLoadingError = false;
continue;
}
if (timeout) break;
InputAnswer();
if (timeout) break;
if (!fileDeleted)
{
if (File.Exists(file))
{
File.Delete(file);
fileDeleted = true;
}
}
if (isRecaptcha1) return "ok";
SubmitAnswer();
if (!needToCheck) return "ok";
if (timeout) break;
Check();
if (success) return "ok";
}
if (timeout) throw new Exception("Loading element timeout is exceeded");
else throw new Exception("Not recognized, Attempts to recognize were ended, before the response was received");
Примечание
Сниппет работает и в случае, когда в браузере используется старый или телефонный юзерагент.
В обязательном порядке необходимо использовать прокси, поскольку после 3-5 распознанных каптч с одного IP ReCaptcha запрещает доступ к аудиофайлу.
Если ReCaptcha не распознаётся с первого раза, сниппет выполнит вторую попытку. Количество попыток загрузить элементы, время ожидания, количество попыток распознать каптчу и необходимость проверки корректности ответа можно менять с помощью переменных:
// время ожидания
var waitTime = 1000;
// количество попыток распознать
var tryRecognize = 10;
// количество попыток загрузить элемент
var tryLoadElement = 60;
// проверять корректность распознанного ответа
var needToCheck = true;
// показывать сообщения о прогрессе распознавания
var needShowMessages = false;
Функция отправки каптчи на сервис выглядит следующим образом:
ZennoPoster.CaptchaRecognition("CapMonster2.dll", str, "CapMonsterModule=ZennoLab.AudioReCaptcha&ParallelMode=true");
, где через знак «&» перечислены параметры сервиса CapMonster2.dll: указание имени модуля и настройка распознавания в параллельном режиме, соответственно.