// Основные параметры
// время ожидания
var waitTime = 1000;
// количество попыток распознать
var tryRecognize = 100;
// количество попыток загрузить элемент
var tryLoadElement = 60;
// получать полный ответ
bool fullAnswer = true;
// показывать сообщения о прогрессе распознавания
var needShowMessages = false;
// проверять корректность распознанного ответа
var needToCheck = true;
// Вспомогательные переменные
// вкладка
var tab = instance.ActiveTab;
// вид рекаптчи 2 (с кнопкой "я не робот" или без)
bool isNewView = true;
// поздравляем, вы не робот
var success = false;
// время вышло
var timeout = false;
// задание для рекапчи 2
var task = string.Empty;
// url изображения
var src = string.Empty;
// картинка в base64
var imageString = string.Empty;
// ответ на каптчу
var answer = string.Empty;
// капча изменилась
var changed = false;
// пустой ответ
var answerIsEmpty = false;
// Проверка прохождения защиты
Action CheckOK= () => {
System.Threading.Thread.Sleep(waitTime); // подождём загрузки элементов
for (int k = 0; k < tryLoadElement; k++)
{
var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
var more = tab.FindElementByAttribute("div", "class", "rc-imageselect-error-select-more", "regexp", 0);
var wrong = tab.FindElementByAttribute("div", "class", "rc-imageselect-incorrect-response", "regexp", 0);
if (!more.IsVoid && !wrong.IsVoid)
{
var isNotVisibleMore = more.GetAttribute("outerhtml").Replace(" ","").Contains("display:none");
var isNotVisibleWrong = wrong.GetAttribute("outerhtml").Replace(" ","").Contains("display:none");
if (isNotVisibleMore && isNotVisibleWrong)
{
if (!check.IsVoid)
{
if (check.OuterHtml.Contains("style=\"\""))
{
success = true;
break;
}
}
else System.Threading.Thread.Sleep(waitTime);
}
else break;
}
if (k == (tryLoadElement - 1)) timeout = true;
}
};
Action UpdateImage= () => {
// Обновляем капчу при необходимости
if (!changed)
{
ZennoLab.CommandCenter. HtmlElement reload = null;
if (isNewView) reload = tab.FindElementByAttribute("div", "id", "recaptcha-reload-button", "text", 0);
else reload = tab.GetDocumentByAddress("0;0").FindElementByTag("form", 1).FindChildByAttribute("input:submit", "class", "fbc-button-reload fbc-button", "regexp", 0);
if (!reload.IsVoid) reload.Click();
else timeout = true;
}
changed = false;
for (int k = 0; k < tryLoadElement; k++)
{
System.Threading.Thread.Sleep(waitTime); // подождём загрузки элемента
// ищем картинку
var testImage = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", 0);
if (testImage.IsVoid) continue;
// получаем url изображания
var newSrc = testImage.GetAttribute("src");
// если изображение изменилось, то выходим
if (newSrc != src) break;
if (k == (tryLoadElement - 1)) timeout = true;
}
};
// Поиск рекаптчи 2
Action SearchReCaptcha2= () => {
project.SendInfoToLog("Поиск рекаптчи 2", needShowMessages);
for (int k = 0; k < tryLoadElement; k++)
{
// поиск кнопки "Я не робот"
var notRobot = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
// если нашли
if (!notRobot.IsVoid)
{
// клик по кнопке
notRobot.Click();
System.Threading.Thread.Sleep(waitTime); // подождём немного
// если ввод каптчи не требуется
var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
if (!check.IsVoid)
{
if (check.OuterHtml.Contains("style=\"\""))
{
success = true;
break;
}
}
// Ждем пока загрузится форма
for (int j = 0; j < tryLoadElement; j++)
{
var loadedForm = tab.FindElementByAttribute("div", "class", "primary-controls", "regexp", 0);
if (!loadedForm.IsVoid) break;
else System.Threading.Thread.Sleep(waitTime); // подождём загрузки элемента
if (j == (tryLoadElement - 1)) timeout = true;
}
break;
}
else
{
// убеждаемся, что это мобильная версия рекапчи
var form = tab.FindElementByAttribute("form", "fulltag", "form", "text", 0);
if (!form.IsVoid)
{
isNewView = false;
fullAnswer = false;
break;
}
else System.Threading.Thread.Sleep(waitTime); // подождём загрузки элемента
}
if (k == (tryLoadElement - 1)) timeout = true;
}
};
// Поиск задания рекапчи 2
Action SearchTask= () => {
project.SendInfoToLog("Поиск задания", needShowMessages);
for (int k = 0; k < tryLoadElement; k++)
{
ZennoLab.CommandCenter.HtmlElement taskHe = null;
if (isNewView) taskHe = tab.FindElementByAttribute("div", "class", "rc-imageselect-desc-wrapper", "regexp", 0);
else taskHe = tab.FindElementByAttribute("label", "class", "fbc-imageselect-message-text", "regexp", 0);
if (!isNewView && taskHe.IsVoid) taskHe = tab.FindElementByAttribute("div", "class", "fbc-imageselect-message-error", "regexp", 0);
if (!taskHe.IsVoid)
{
task = taskHe.GetAttribute("innertext"); // получаем задание
string suspecttask = task.ToLower();
if (suspecttask.Contains("Click verify once there are none left") || suspecttask.Contains("Когда изображения закончатся"))
throw new Exception("Не распознано");
if (suspecttask.Contains("street signs") || suspecttask.Contains("указатели") || suspecttask.Contains("дорожні знаки") || suspecttask.Contains("дорожные знаки"))
{
UpdateImage();
continue;
}
break;
}
else System.Threading.Thread.Sleep(waitTime); // подождём загрузки элемента
if (k == (tryLoadElement - 1)) timeout = true;
}
};
// Поиск изображения
Action SearchImage= () => {
project.SendInfoToLog("Поиск изображения", needShowMessages);
System.Threading.Thread.Sleep(waitTime * 3); // подождём загрузки элемента
for (int k = 0; k < tryLoadElement; k++)
{
ZennoLab.CommandCenter.HtmlElement image = null;
if (isNewView) image = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", 0);
else image = tab.FindElementByAttribute("img", "class", "fbc-imageselect-payload", "regexp", 0);
// если есть изображение
if (!image.IsVoid)
{
// получаем url изображания
src = image.GetAttribute("src");
imageString = image.DrawToBitmap(true);
break;
}
else System.Threading.Thread.Sleep(waitTime); // подождём загрузки элемента
if (k == (tryLoadElement - 1)) timeout = true;
}
};
// Распознавание
Action Recognize= () => {
project.SendInfoToLog("Распознавание", needShowMessages);
if (!isNewView) fullAnswer = false;
var answerString = ZennoPoster.CaptchaRecognition("CapMonster2.dll", imageString, String.Format("Task={0}&FullAnswer={1}", task, fullAnswer));
var split = answerString.Split(new [] { "-|-" }, StringSplitOptions.RemoveEmptyEntries);
answer = split[0];
};
//Вводим ответ
Action InputAnswer= () => {
if (!String.IsNullOrEmpty(answer) && answer != "sorry")
{
project.SendInfoToLog("Ввод ответа и проверка правильности", needShowMessages);
int count = 0;
foreach (char c in answer)
{
if (fullAnswer)
{
if (count == 2) break;
}
int index;
ZennoLab.CommandCenter.HtmlElement he = null;
if (isNewView)
{
index = Convert.ToInt32(c.ToString()) - 1;
he = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", index);
}
else
{
string attrValue = "fbc-imageselect-checkbox-" + c;
he = tab.FindElementByAttribute("input:checkbox", "class", attrValue, "regexp", 0);
}
if (!he.IsVoid)
{
he.Click(); //кликаем на картинку
System.Threading.Thread.Sleep(waitTime);// подождём немного
}
if (fullAnswer) count++;
}
// ищем кнопку "Подтвердить"
ZennoLab.CommandCenter.HtmlElement apply = null;
if (isNewView) apply = tab.FindElementById("recaptcha-verify-button");
else apply = tab.GetDocumentByAddress("0;0").FindElementByTag("form", 0).FindChildByAttribute("input:submit", "fulltag", "input:submit", "text", 0);
if (!apply.IsVoid) apply.Click();
// проверим правильность ответа
if (isNewView)
{
CheckOK();
if (success) return;
// вводим оставшуюся часть ответа
if (fullAnswer)
{
for (int i = count; i < answer.Length; i++)
{
// снова ищем картинку
var testImage = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", 0);
if (testImage.IsVoid) break;
// получаем url изображания
var newSrc = testImage.GetAttribute("src");
// если изображение изменилось, то выходим
if (newSrc != src) break;
else changed = true;
// иначе продолжаем ввод
int index = Convert.ToInt32(answer[i].ToString()) - 1;
var he = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", index);
if (!he.IsVoid)
{
he.Click();
System.Threading.Thread.Sleep(waitTime); // подождём немного
if (!apply.IsVoid) apply.Click();
CheckOK();
if (success) return;
}
}
}
}
}
else answerIsEmpty = true;
};
// Дополнительные действия для старого вида рекапчи
Action ActsOldView= () => {
System.Threading.Thread.Sleep(waitTime * 3); // подождём загрузки элемента
// Проверяем, была ли ошибка в распознавании
ZennoLab.CommandCenter.HtmlElement he = tab.FindElementByAttribute("img", "class", "fbc-imageselect-payload", "regexp", 0);
if (!he.IsVoid)
{
return;
}
string txt = string.Empty;
// ищем текст, который надо вставить
for (int k = 0; k < tryLoadElement; k++)
{
ZennoLab.CommandCenter.HtmlElement heGetText = tab.FindElementByAttribute("textarea", "dir", "ltr", "regexp", 0);
if (!heGetText.IsVoid)
{
txt = heGetText.GetAttribute("value");
break;
}
else
{
System.Threading.Thread.Sleep(waitTime); // подождём немного
continue;
}
if (k == (tryLoadElement - 1)) timeout = true;
}
// ищем куда вставлять текст
for (int k = 0; k < tryLoadElement; k++)
{
ZennoLab.CommandCenter.HtmlElement hePutText = tab.FindElementByAttribute("textarea", "id", "g-recaptcha-response", "regexp", 0);
if (!hePutText.IsVoid)
{
hePutText.SetValue(txt, "None", false);
break;
}
else
{
System.Threading.Thread.Sleep(waitTime); // подождём немного
continue;
}
if (k == (tryLoadElement - 1)) timeout = true;
}
// нажимаем "Подтвердить"
for (int k = 0; k < tryLoadElement; k++)
{
var submit = tab.FindElementByAttribute("input:submit", "fulltag", "input:submit", "regexp", 0);
if (!submit.IsVoid)
{
submit.Click();
break;
}
else
{
System.Threading.Thread.Sleep(waitTime); // подождём немного
continue;
}
if (k == (tryLoadElement - 1)) timeout = true;
}
success = true;
};
SearchReCaptcha2();
if (timeout) throw new Exception("Вышло время ожидания загрузки элемента");
for (int i = 0; i < tryRecognize; i++)
{
SearchTask();
if (timeout) break;
SearchImage();
if (timeout) break;
Recognize();
InputAnswer();
if (!needToCheck) return "ok";
if (answerIsEmpty)
{
answerIsEmpty = false;
UpdateImage();
continue;
}
if (!isNewView) ActsOldView();
if (timeout) break;
if (success) return "ok";
if (i != (tryRecognize - 1)) UpdateImage();
if (timeout) break;
}
if (timeout) throw new Exception("Вышло время ожидания загрузки элемента");
else throw new Exception("Не распознано. Закончились попытки распознать, прежде чем ответ был засчитан");