Инструменты пользователя

Инструменты сайта


Боковая панель

Перевод этой страницы:

ru:addons:capmonster:rc2

ReCaptcha 2

С недавних пор, компания Google выпустила новую версию защиты от ботов. На веб-странице появляется кнопка «Я не робот», при нажатии на которую появляется несколько картинок, среди которых нужно выбрать все изображения, указанные в заголовке.

Выглядит это так:

Пример можно посмотреть тут: Демо-страница от google

Включение распознавания в CapMonster

В программе CapMonster 2, начиная с версии 2.4.0.0 появилась возможность распознавать новую ReCaptcha2. Функция распознавания на данный момент находится в режиме тестирования. Для нее необходимо скачать дополнительный файл (около 600МБ), который мы не стали включать в релиз.

При отправке каптчи в CapMonster2 вам необходимо сформировать запрос, который будет включать изображение из 9 вариантов ответов и задание в виде дополнительного параметра. Имя параметра: «Task». Значение - вопрос самой рекапчи, например «Выберите все изображения, где есть мороженное»

Требования к системе:

1) Windows 64 bit
2) Более 2Гб RAM.

Скачать CMconnector для CapMonster 2.4.1.2 и выше:

CMconnector.exe

После загрузки, его необходимо положить в папку с программой, как показано на скриншоте:

В CapMonster с версии 2.4.0.0 и выше, у вас будет доступен модуль ZennoLab.ReCaptcha2. Он должен быть активен.



Как это работает

CapMonster 2 присылает ответ в виде строки состоящей из цифр - номеров картинок без разделителей на которые надо кликнуть. Номера указываются в порядке убывания вероятности, что на картинке изображен указанный предмет.

Например, нам надо выбрать картинки, где изображены пончики. CapMonster 2 приcлал ответ 328. Значит необходимо кликнуть на 3, 2 и 8 картинку, а затем нажать кнопку «Подтвердить». То есть, 3 картинка вероятнее всего содержит пончик, затем 2 и 8.

Если CapMonster не смог распознать пончики на более чем одной картинке (2 картинки - минимально возможное количество правильных ответов) , то он присылает пустой ответ для того, чтобы вы могли отправить эту каптчу на сервис ручного распознавания.

Использование в ZennoPoster

Для отправки каптч ReCaptcha2 из ZennoPoster версии более 5.9 вы можете использовать подготовленный нами сниппет:

// Основные параметры
 
// время ожидания
var waitTime = 1000;
// количество попыток распознать
var tryRecognize = 3;
// количество попыток загрузить элемент
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) 
	{
		HtmlElement reload = null;
		if (isNewView) reload = tab.FindElementById("recaptcha-reload-button");
		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++)
	{
		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("дорожні знаки")) 
			{
				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++)
	{
		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;
 
			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++;
		}
 
		// ищем кнопку "Подтвердить"
		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); // подождём загрузки элемента
	// Проверяем, была ли ошибка в распознавании
	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++)
	{
		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++)
	{
		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("Не распознано. Закончились попытки распознать, прежде чем ответ был засчитан");
 

Примечание

На данный момент CapMonster2 обрабатывает только те капчи, задания которых указаны на русском, английском, украинском и итальянском языках.

Сниппет может выполнять любое количество попыток разгадать каптчу. Также если вы используете медленные прокси, можно увеличить время ожидания загрузки элементов, количество попыток загрузки и настройка необходимости проверки правильности распознанного ответа. Для этого вы можете менять параметры:

// время ожидания
var waitTime = 1000;
// количество попыток распознать
var tryRecognize = 3;
// количество попыток загрузить элемент
var tryLoadElement = 60;
// проверять корректность распознанного ответа
var needToCheck = true;

Все, описанные в предыдущем разделе действия, сниппет выполняет с одним уточнением: он сначала кликает на 2 картинки (минимально возможное количество правильных ответов), затем нажимает «подтвердить». Если этих ответов недостаточно, то сниппет кликает на следующую картинку, нажимает «подтвердить» и так далее.

Это сделано потому, что ReCaptcha может засчитать ответ, в котором не хватает одной картинки или ответ, где одна из картинок может быть указана не правильно, то есть таким способом мы избавляемся от возможных ошибок.

В случае, когда в браузере используется старый или телефонный UserAgent, ReCaptcha2 имеет другой вид (например, отсутствует кнопка «я не робот»), клики производятся на чекбоксы каждой необходимой картинки

В зависимости от IP-адреса, с которого вы производите вышеописанные манипуляции, ReCaptcha2 может «закрыть глаза» на нехватку клика на одну из картинок или на клик на неправильную картинку. Однако, при постоянных ошибках, ReCaptcha2 может не принимать даже правильные ответы, поэтому рекомендуется использовать хорошие прокси.

Процент пробива ReCaptcha 2 при таком подходе выше, чем при способе, когда клики производятся сразу на все указанные картинки, а затем производится нажатие кнопки «Подтвердить». Но доступна и такая возможность, например, для отправки каптч в CapMonster 2 не из ZennoPoster.

Для этого нужно заменить:

bool fullAnswer = true;

на:

bool fullAnswer = false;
ru/addons/capmonster/rc2.txt · Последние изменения: 2016/12/09 10:29 — afameless