// ==================== Все что нужно настроить ========================================
bool extendAlerts = true; // true - выводить сообщения в лог ZennoPoster
string alertTitleLog = "Google ReCaptcha:"; // Заголовок перед сообщением в логе
string captchaModule = "RuCaptcha.dll"; // Можно RuCaptcha.dll или MonkeyEnter.dll
int checkElementTimeout = 10; // Время, в течении которого ищем элементы на странице
int captchaLoadTimeout = 5; // Время ожидания загрузки формы с картинками
int checkCaptchaCount = 3; // Количество попыток разгадывания
// =====================================================================================
// ========== Цикл по количеству попыток разгадывания капчи ==========
for (int i = 0; i < checkCaptchaCount; i++)
{
project.SendInfoToLog("Разгадываем капчу. Попытка " + Convert.ToString(i + 1) + "/" + checkCaptchaCount, alertTitleLog, extendAlerts);
// ========== Цикл по времени поиска элемента recaptcha-checkbox на странице ==========
for (int j = 0; j < checkElementTimeout * 2; j++)
{
System.Threading.Thread.Sleep(500);
// ========== Кликаем ReCaptcha checkbox ==========
HtmlElement reCaptcha_checkbox = instance.ActiveTab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
if (!reCaptcha_checkbox.IsNull && !reCaptcha_checkbox.IsVoid)
{
reCaptcha_checkbox.Click();
break;
}
if (j == checkElementTimeout * 2 - 1)
{
project.SendWarningToLog("Время поиска элемента истекло. Не найден элемент <recaptcha-checkbox>", alertTitleLog, extendAlerts);
throw new Exception();
}
}
// ========== Проверяем нужные элементы после клика ==========
string reCaptcha_isChecked = string.Empty; // Состояние чекбокса. false - значит нужно разгадывать картинки
HtmlElement imgForm = null;
//HtmlElement imgText = null;
string imgText = string.Empty;
bool oldRecaptcha = false;
for (int j = 0; j < checkElementTimeout * 2; j++)
{
System.Threading.Thread.Sleep(500);
// ========== Получаем состояние чекбокса ==========
HtmlElement reCaptcha_checked = instance.ActiveTab.FindElementByAttribute("span", "id", "recaptcha-anchor", "regexp", 0);
if (!reCaptcha_checked.IsNull && !reCaptcha_checked.IsVoid)
{
reCaptcha_isChecked = reCaptcha_checked.GetAttribute("aria-checked");
if (reCaptcha_isChecked == "true")
break;
}
// ========== Ищем форму с картинками на странице ==========
imgForm = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-imageselect-payload", "regexp", 0);
var imgs = instance.ActiveTab.FindElementsByAttribute("div", "class", "rc-imageselect-checkbox", "regexp");
if (!imgs.IsVoid && !imgForm.IsNull && !imgForm.IsVoid && imgs.Count > 0)
{
if (captchaModule == "RuCaptcha.dll" && imgs.Count == 16)
{
imgForm = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-imageselect-challenge", "regexp", 0);
var heText = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-imageselect-desc", "regexp", 0);
imgText = Regex.Replace(heText.GetAttribute("innerhtml"), "<[^>]+>", string.Empty);
if (imgText == "")
{
heText = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-imageselect-desc-no-canonical", "regexp", 0);
imgText = Regex.Replace(heText.GetAttribute("innerhtml"), "<[^>]+>", string.Empty);
}
}
else
{
oldRecaptcha = true;
imgForm = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-imageselect-payload", "regexp", 0);
}
break;
}
}
if (reCaptcha_isChecked != "true")
System.Threading.Thread.Sleep(captchaLoadTimeout * 1000); // Делаем паузу, ждем пока подгрузятся картинки
// ========== Разгадываем капчу ==========
string recognition_Result = string.Empty; // Результат разгадывания
string recognition_WrongCaptcha = string.Empty; // Ссылка для возврата ошибки на сервис RuCaptcha.com
if (reCaptcha_isChecked == "false")
{
// Проверяем попалась ли капча с одной картинкой
if (imgForm.IsVoid)
{
project.SendInfoToLog("Не найдена форма с картинками. Скорее всего вылезла старая капча.", alertTitleLog, extendAlerts);
break;
}
// Снимаем отметки с картинок
var imgs = instance.ActiveTab.FindElementsByAttribute("div", "class", "rc-imageselect-checkbox", "regexp");
if (!imgs.IsVoid)
{
for (int k = 0; k < imgs.Count; k++)
{
string width = imgs.GetByNumber(k).GetAttribute("width");
if (width != "" && width != "0")
imgs.GetByNumber(k).Click();
}
}
// Скриним форму с картинками и конвертируем в jpg
string attribute = imgForm.DrawToBitmap(false);
MemoryStream ms = new System.IO.MemoryStream(Convert.FromBase64String(attribute));
Image bmp = new Bitmap(ms);
var msJpeg = new System.IO.MemoryStream();
string jpeg = string.Empty;
if (captchaModule == "MonkeyEnter.dll" || oldRecaptcha)
{
bmp.Save(msJpeg, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else
{
Image imgNew = new Bitmap(600, 600);
var g = Graphics.FromImage(imgNew);
g.DrawImage(bmp, 0, 0, 600, 600);
g.Dispose();
imgNew.Save(msJpeg, System.Drawing.Imaging.ImageFormat.Jpeg);
imgNew.Dispose();
}
jpeg = Convert.ToBase64String(msJpeg.ToArray());
bmp.Dispose();
// Отправляем на распознавание
project.SendInfoToLog("Отправляем данные на сервис распознавания", alertTitleLog, extendAlerts);
string answer = string.Empty;
if (captchaModule == "MonkeyEnter.dll" || oldRecaptcha)
answer = ZennoPoster.CaptchaRecognition(captchaModule, jpeg, "id_constructor=23");
else
answer = ZennoPoster.CaptchaRecognition(captchaModule, jpeg, "textinstruction=" + imgText + "&recaptcha=1");
// Приводим результат распознавания к нужному виду
if (captchaModule == "RuCaptcha.dll")
{
// Разделяем ответ от RuCaptcha и складыванем в переменные
var split = answer.Split(new [] { "-|-" }, StringSplitOptions.RemoveEmptyEntries);
if (split.Length == 2)
{
recognition_Result = split[0];
recognition_WrongCaptcha = split[1];
}
else
{
project.SendInfoToLog("Error: не удалось разгадать капчу", alertTitleLog, extendAlerts);
continue;
}
// Проверяем ответ sorry
if (recognition_Result == "sorry")
{
project.SendInfoToLog("Капча не распознана. RuCaptcha: sorry", alertTitleLog, extendAlerts);
continue;
}
// Обрезаем начало ответа, оставляем только номера картинок, разделенные /
recognition_Result = Regex.Match(recognition_Result, @"(?<=click:).*").Value;
}
else
recognition_Result = answer;
// Отображаем скрывшуюся капчу
var e = instance.ActiveTab.FindElementByAttribute("div", "outerhtml", "z-index: 20000000", "regexp", 0);
e.SetAttribute("style", "display: block; visibility: visible; position: absolute; width: 414px; left: 0px; top: 0px; height: 600px; z-index: 2000000000;");
// ===== Кликаем =====
do
{
// Выдераем номера картинок и кликаем по ним
// Проверяем тип ответа
string img_split = Regex.Match(recognition_Result, @"/").Value;
if (img_split != "")
{
if (Regex.Match(recognition_Result, @"/$").Value == "")
recognition_Result += "/";
img_split = Regex.Match(recognition_Result, @"^\d{1,2}(?=/)").Value;
if (img_split == "")
img_split = Regex.Match(recognition_Result, @"^\d{1,2}").Value;
if (img_split == "")
recognition_Result = Regex.Match(recognition_Result, @"(?<=^/).*").Value; // обрезаем разделитель / в начале строки
else
{
recognition_Result = Regex.Match(recognition_Result, @"(?<=^\d{1,2}/).*").Value; // обрезаем число и разделитель / в начале строки
}
}
else
{
img_split = Regex.Match(recognition_Result, @"^\d{1}").Value;
recognition_Result = Regex.Match(recognition_Result, @"(?<=^\d{1}).+").Value;
}
// Получаем картинку и кликаем
string width = "0";
HtmlElement img = instance.ActiveTab.FindElementByAttribute("img", "class", "rc-image-tile-4", "regexp", Convert.ToInt32(img_split) - 1);
if (img.IsVoid)
{
img = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-image-tile-target", "regexp", Convert.ToInt32(img_split) - 1);
if (img.IsVoid)
img = instance.ActiveTab.FindElementByAttribute("div", "class", "rc-image-tile-wrapper", "regexp", Convert.ToInt32(img_split) - 1);
}
img.Click();
System.Threading.Thread.Sleep(500);
}
while (recognition_Result != "");
// ========= Подтверждаем =========
var verify_button = instance.ActiveTab.FindElementByAttribute("div", "id", "recaptcha-verify-button", "regexp", 0);
if (!verify_button.IsVoid && !verify_button.IsNull)
{
verify_button.Click();
}
// ========== Проверяем разгадали ли ==========
string captchaError = string.Empty; // Тип ошибки
reCaptcha_isChecked = string.Empty; // Состояние чекбокса. false - значит нужно разгадывать картинки
for (int j = 0; j < 10; j++)
{
System.Threading.Thread.Sleep(500);
// Получаем состояние чекбокса
HtmlElement reCaptcha_checked = instance.ActiveTab.FindElementByAttribute("span", "id", "recaptcha-anchor", "regexp", 0);
if (!reCaptcha_checked.IsNull && !reCaptcha_checked.IsVoid)
{
reCaptcha_isChecked = reCaptcha_checked.GetAttribute("aria-checked");
if (reCaptcha_isChecked == "true")
break;
}
string textDom = instance.ActiveTab.DomText;
// Получаем ошибку
captchaError = Regex.Match(textDom, @"(?<=<div\ class=""rc-imageselect-error-select-one""\ style="").*?(?="">)").Value;
if (captchaError == "")
{
captchaError = "1";
break;
}
captchaError = Regex.Match(textDom, @"(?<=<div\ class=""rc-imageselect-error-select-more""\ style="").*?(?="">)").Value;
if (captchaError == "")
{
captchaError = "2";
break;
}
captchaError = Regex.Match(textDom, @"(?<=<div\ class=""rc-imageselect-incorrect-response""\ style="").*?(?="">)").Value;
if (captchaError == "")
{
captchaError = "3";
break;
}
}
// ========= Отправляем ошибки на RuCaptcha =========
if (reCaptcha_isChecked == "false")
{
if (captchaModule == "RuCaptcha.dll")
ZennoPoster.HttpGet(recognition_WrongCaptcha, "", "UTF-8", ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.BodyOnly, 30000, "", "", true, 5, AdditionalHeaders: new [] {"Referer: "+ ""});
if (captchaError == "1")
project.SendInfoToLog("Капча разгадана не верно! Нужно указать еще одно изображение.", alertTitleLog, extendAlerts);
if (captchaError == "2")
project.SendInfoToLog("Капча разгадана не верно! Нужно указать больше изображений.", alertTitleLog, extendAlerts);
if (captchaError == "3")
project.SendInfoToLog("Капча разгадана не верно! Нужно попытаться еще.", alertTitleLog, extendAlerts);
continue;
}
}
// ========= Все ОК =========
project.SendInfoToLog("Капча успешно разгадана!", alertTitleLog, extendAlerts);
return "ok";
}
// Количество попыток разгадывания превышено, завершаем экшен по неудаче
throw new Exception();