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

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


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

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

ru:addons:capmonster:rc2

ReCaptcha 2

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

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

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

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

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

При отправке каптчи в CapMonster2 вам необходимо сформировать запрос, который будет включать изображение из нескольких вариантов ответов и задание в виде дополнительного параметра. Имя параметра: «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 для версии CapMonster 2.8.3.0 и выше вы можете использовать подготовленный нами кубик Распознать ReCaptcha2:

Также в кубике можно изменять параметры распознавания, которые используются в сниппете, приведенном ниже.

Также ReCaptcha2 можно распознавать через Sitekey, указав SiteKey и URL страницы

Также на некоторых сайтах после выбора картинок появляется событие autosubmit. После его выполнения капча засчитывается. В ZennoPoster также можно работать с autosubmit.

Для отправки каптч ReCaptcha2 из ZennoPoster версии более 5.9 вы можете использовать подготовленный нами сниппет:
(Данный сниппет актуален для версии Capmonster 2.6.3+. Старый сниппет, который работал с предыдущей версией второй (версия CapMonster 2.6.2 и ниже) рекаптчи доступен здесь)


// Основные параметры
 
// время ожидания
var waitTime = 1500;
// количество попыток распознать
var tryRecognize = 10;
// количество попыток выбирать изменяющиеся картинки
var dynamicImagesRecognizeAttempts = 20;
// количество попыток загрузить элемент
var tryLoadElement = 60;
// получать полный ответ
bool fullAnswer = false;
// показывать сообщения о прогрессе распознавания
var needShowMessages = false;
// проверять корректность распознанного ответа
var needToCheck = true;
 
// Вспомогательные переменные
 
// вкладка
Tab tab = instance.ActiveTab;
// поздравляем, вы не робот
var success = false;
// время вышло
var timeout = false;
// задание для рекапчи 2
string task = string.Empty;
// url изображения
var src = string.Empty;
// картинка в base64
var imageString = string.Empty;
// ответ на каптчу
string answer = string.Empty;
// капча изменилась
var changed = false;
// пустой ответ
bool answerIsEmpty = false;
// изменяемая каптча
bool dynamicCaptcha = false;
// ввод каптчи несколько раз
bool notOneEnter = false;
var coincidenceReCaptcha2Index = -1;
 
// Проверка прохождения защиты
Action CheckOK= () => 
{
	tab.WaitDownloading();
	for (int k = 0; k < tryLoadElement; k++)
	{
		System.Threading.Thread.Sleep(waitTime); // подождём загрузки элементов
		var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
 
		// проверка исчезновения формы
		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 (check.IsVoid)
				break;
		}
 
		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 break;
				}
			}
			else break;
		}
		if (k == (tryLoadElement - 1)) timeout = true;
 
	}
};
 
// Подтверждение ответа
Action VerifyAnswer= () =>
{
	project.SendInfoToLog("Проверка правильности после ввода динамической капчи", needShowMessages);
 	tab.WaitDownloading();
	// поиск кнопки "Подтвердить"
	HtmlElement apply = tab.FindElementById("recaptcha-verify-button");
	if (!apply.IsVoid) apply.Click();
	// проверка правильности ответа
	CheckOK();
};
 
Action InputNotBotText= () =>
{
	tab.WaitDownloading();
	var inputField = tab.FindElementByAttribute("input:text", "id", "default-response", "text", 0);
	if (!inputField.IsVoid)
	{
		inputField.SetValue("I am not robot", "Full");
		VerifyAnswer();
	}
};
 
Action UpdateImage= () => 
{
	project.SendInfoToLog("Обновление капчи", needShowMessages);
 
	// Обновить капчу если необходимо
	if (!changed) 
	{
		HtmlElement reload = tab.FindElementById("recaptcha-reload-button");
 
		if (!reload.IsVoid)
		{
			reload.Click();
			InputNotBotText();
		}
		else timeout = true;
	}
	changed = false;
 
	for (int k = 0; k < tryLoadElement; k++)
	{
		System.Threading.Thread.Sleep(waitTime); // waiting for element load
		// searching for the picture
		var testImage = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", 0);
		if (testImage.IsVoid) continue;
		// get image url
		var newSrc = testImage.GetAttribute("src");
		// if the image has been changed, go out
		if (newSrc != src) break;
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
Action VisibleIndexReCaptchaDefinition= () => {
	tab.WaitDownloading();
	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;
			}
		}
	}
};
 
// Поиск рекаптчи 2
Action SearchReCaptcha2= () => 
{
	project.SendInfoToLog("Поиск рекапчи 2", needShowMessages);
 	tab.WaitDownloading();
	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); // pause
 
			// если ввод капчи не требуется
			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;
 
		// подождем загрузки элементов
		System.Threading.Thread.Sleep(waitTime);
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// Поиск задания рекапчи 2
Action SearchTask= () => 
{
	tab.WaitDownloading();
	project.SendInfoToLog("Поиск задания", needShowMessages);
	dynamicCaptcha = false;
	notOneEnter = false;
	answer = String.Empty;
 
	for (int k = 0; k < tryLoadElement; k++)
	{
		HtmlElement taskHe = tab.FindElementByAttribute("div", "class", "rc-imageselect-desc-wrapper", "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("when images will be end") || suspecttask.Contains("когда изображения закончатся") || suspecttask.Contains("коли зображень уже не залишиться, натисніть \"підтвердити\"") || suspecttask.Contains("fai clic su Verifica dopo averle selezionate tutte")) dynamicCaptcha = true;
			if (suspecttask.Contains("if there are none, click skip") || suspecttask.Contains("if they do not exist, click \"skip\"") || suspecttask.Contains("если их нет, нажмите \"пропустить\"") || suspecttask.Contains("якщо нічого немає") || suspecttask.Contains("se non ne vedi, fai clic su salta")) notOneEnter = true;
			timeout = false;
			break;	
		}
 
		System.Threading.Thread.Sleep(waitTime); // подождём загрузки элемента
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// Поиск изображения
Action SearchImage= () => 
{
	tab.WaitDownloading();
	project.SendInfoToLog("Поиск изображения", needShowMessages);
 
	for (int k = 0; k < tryLoadElement; k++)
	{
		HtmlElement image = null;
		if (dynamicCaptcha) image = tab.FindElementByAttribute("table", "class", "rc-imageselect-table", "regexp", 0); 
		else image = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", 0);
 
		// если есть изображения
		if (!image.IsVoid)
		{
			// получаем url изображения
			if (!dynamicCaptcha) src = image.GetAttribute("src");
			imageString = image.DrawToBitmap(!dynamicCaptcha);
			timeout = false;
			break;
		}
 
		System.Threading.Thread.Sleep(waitTime); // подождем загрузки элементов
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// Распознавание
Action Recognize= () => {
	project.SendInfoToLog("Распознавание", needShowMessages);
	var answerString = ZennoPoster.CaptchaRecognition("CapMonster2.dll", imageString, String.Format("Task={0}&FullAnswer={1}&CapMonsterModule=ZennoLab.ReCaptcha2", 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;
 
        string[] answers;
		if (answer.Contains(",")) 
			answers = answer.Split(new [] { "," }, StringSplitOptions.RemoveEmptyEntries);
		else 
		{
			answers = new string[answer.Length];
			for (int i = 0; i < answer.Length; i++)
				answers[i] = answer[i].ToString();
		}
 
		foreach (string c in answers)
		{
			if (fullAnswer)
				if (count == 2) break;
 
			int index = Convert.ToInt32(c) - 1;
			HtmlElement he = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", index);
 
			if (!he.IsVoid) 
			{
				he.Click(); //кликаем на картинку
				System.Threading.Thread.Sleep(500);// подождем немного
			}
			if (fullAnswer) count++;
		}
 
		// ищем кнопку "Подтвердить"
		HtmlElement apply = tab.FindElementById("recaptcha-verify-button");
		if (!apply.IsVoid) apply.Click();
 
		// проверим правильность ответа
		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(500); // подождем немного
					if (!apply.IsVoid) apply.Click();
					CheckOK();
					if (success) return;
				}
			}
		}
	}
	else answerIsEmpty = true;
};
 
//Вводим ответ
Action InputDynamicAnswer= () => 
{
	project.SendInfoToLog("Ввод ответа динамической каптчи", needShowMessages);
 
	string[] answers;
	if (answer.Contains(",")) 
		answers = answer.Split(new [] { "," }, StringSplitOptions.RemoveEmptyEntries);
	else 
	{
		answers = new string[answer.Length];
		for (int i = 0; i < answer.Length; i++)
			answers[i] = answer[i].ToString();
	}
 
	foreach (string number in answers)
	{
		int index = Convert.ToInt32(number) - 1;
		HtmlElement he = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", index);
		if (he.IsVoid) he = tab.FindElementByAttribute("div", "class", "rc-image-tile-wrapper", "regexp", index);
		if (!he.IsVoid) 
		{
			//кликаем на картинку
			he.Click();
			// подождём немного
			System.Threading.Thread.Sleep(500);
		}
	}
 
	// подождём еще немного
	System.Threading.Thread.Sleep(waitTime*2);
};
 
//Вводим ответ
Action InputDynamicAnswer2= () => 
{
	project.SendInfoToLog("Ввод ответа динамической каптчи", needShowMessages);
 
	string[] answers = answer.Split(new [] { "," }, StringSplitOptions.RemoveEmptyEntries);
	foreach (string number in answers)
	{
		int index = Convert.ToInt32(number) - 1;
		HtmlElement he = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", index);
		if (!he.IsVoid) 
		{
			//кликаем на картинку
			he.Click();
			// подождём немного
			System.Threading.Thread.Sleep(500);
		}
	}
 
	// подождём еще немного
	System.Threading.Thread.Sleep(waitTime*2);
};
 
SearchReCaptcha2();
if (success)
	return "ok";
 
if (timeout) throw new Exception("Вышло время ожидания загрузки элемента");
 
for (int i = 0; i < tryRecognize; i++)
{
	project.SendInfoToLog(String.Format("Попытка №:{0}", i+1), needShowMessages);
 
	InputNotBotText();
	SearchTask();
	if (timeout) break;
 
	// дополнительная проверка
	CheckOK();
	if (success) return "ok";
 
	int count = 0;
 
	// если капча изменяемая
	if (dynamicCaptcha)
	{
		while (count < dynamicImagesRecognizeAttempts)
		{
			if (count > 0)
				System.Threading.Thread.Sleep(waitTime * 3); // подождём загрузки исчезающих изображений
 
			SearchImage();
			if (timeout) break;
			Recognize();
			if (!String.IsNullOrEmpty(answer) && answer != "sorry") InputDynamicAnswer();
			else 
			{
				VerifyAnswer();
				CheckOK();
				if (!success) answerIsEmpty = true;
				break;
			}
			count++;
		}
	}
	else
	{
		if (notOneEnter)
		{
			while (notOneEnter && !dynamicCaptcha && count < dynamicImagesRecognizeAttempts)
			{
				SearchImage();
				if (timeout) break;
				Recognize();
				if (!String.IsNullOrEmpty(answer) && answer != "sorry") InputDynamicAnswer2();
				VerifyAnswer();
				timeout = false;
				if (success) break;
				SearchTask();
				if (timeout) break;
				count++;
			}
		}
		else
		{
			SearchImage();
			if (timeout) break;
			Recognize();
			InputAnswer();
		}
	}
	if (timeout) break;
 
	if (!needToCheck) return "ok";
 
	if (answerIsEmpty)
	{
		answerIsEmpty = false;
		UpdateImage();
		continue;
	}
 
	if (success) return "ok";
 
	if (i != (tryRecognize - 1)) UpdateImage();
	if (timeout) break;
}
 
if (timeout) throw new Exception("Вышло время ожидания загрузки элемента");
else throw new Exception("Не распознано. Закончились попытки распознать, прежде чем ответ был засчитан");
 

Примечание

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

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

// время ожидания
var waitTime = 3000;
// количество попыток распознать
var tryRecognize = 10;
// количество попыток выбрать изменяющиеся картинки
var dynamicImagesRecognizeAttempts = 20;
// количество попыток загрузить элемент
var tryLoadElement = 60;
// получить полный ответ
bool fullAnswer = false;
// получить сообщения о прогрессе распознавания
var needShowMessages = false;
// проверять корректность распознанного ответа
var needToCheck = true;

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

ru/addons/capmonster/rc2.txt · Последние изменения: 2017/09/22 15:26 — copper12