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

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


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

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

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 версии более 5.9 вы можете использовать подготовленный нами сниппет:
(Данный сниппет актуален для версии Capmonster 2.6.3+. Старый сниппет, который работал с предыдущей версией второй (версия CapMonster 2.6.2 и ниже) рекаптчи доступен здесь)


// Main parameters
 
// waiting time
var waitTime = 1500;
// the number of recognition attempts
var tryRecognize = 10;
// the number of attempts to choose dynamic pictures
var dynamicImagesRecognizeAttempts = 20;
// the number of attempts to load the element
var tryLoadElement = 60;
// get the full answer
bool fullAnswer = false;
// show the messages about recognition progress
var needShowMessages = false;
// check correctness of the recognized answer
var needToCheck = true;
 
// Secondary variables
 
// tab
Tab tab = instance.ActiveTab;
// congratulations, you are not a robot
var success = false;
// time is over
var timeout = false;
// task for recaptcha 2
string task = string.Empty;
// image url
var src = string.Empty;
// picture in base64 format
var imageString = string.Empty;
// answer for the captcha
string answer = string.Empty;
// the captcha has been changed
var changed = false;
// empty answer
bool answerIsEmpty = false;
// dynamic captcha
bool dynamicCaptcha = false;
// input the captcha several times
bool notOneEnter = false;
var coincidenceReCaptcha2Index = -1;
 
// Checking of protection passing
Action CheckOK= () => 
{
	tab.WaitDownloading();
	for (int k = 0; k < tryLoadElement; k++)
	{
		System.Threading.Thread.Sleep(waitTime); // waiting for element load
		var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
 
		// checking the form's disappearing
		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;
 
	}
};
 
// Confirmation of the answer
Action VerifyAnswer= () =>
{
	project.SendInfoToLog("Checking correctness after input of dynamic captcha", needShowMessages);
 	tab.WaitDownloading();
	// searching for the button "Submit"
	HtmlElement apply = tab.FindElementById("recaptcha-verify-button");
	if (!apply.IsVoid) apply.Click();
	// checking correctness of the answer
	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("Captcha's update", needShowMessages);
 
	// Update of the captcha if it is necessary
	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;
			}
		}
	}
};
 
// Searching for recaptcha 2
Action SearchReCaptcha2= () => 
{
	project.SendInfoToLog("Searching for recaptcha 2", needShowMessages);
 	tab.WaitDownloading();
	for (int k = 0; k < tryLoadElement; k++)
	{
		VisibleIndexReCaptchaDefinition();
		if (coincidenceReCaptcha2Index < 0) coincidenceReCaptcha2Index = 0;
 
		// searching for the button "I am not a robot"
		HtmlElement notRobot = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
 
		// the button exists
		if (!notRobot.IsVoid)
		{
			// click to the button
			notRobot.Click();
			System.Threading.Thread.Sleep(waitTime); // pause
 
			// if input of the captcha is not necessary
			var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
			if (!check.IsVoid)
			{
				if (check.OuterHtml.Contains("style=\"\""))
				{
					success = true;
					timeout = false;
					break;
				}
			}
		}
 
		// the form exists
		var loadedForm = tab.FindElementByAttribute("div", "class", "primary-controls", "regexp", 0);
		if (!loadedForm.IsVoid)
			break;
 
		// waiting for element load
		System.Threading.Thread.Sleep(waitTime);
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// searching for recaptcha 2 task
Action SearchTask= () => 
{
	tab.WaitDownloading();
	project.SendInfoToLog("Searching for the task", 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"); // getting the task
			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); // waiting for load element
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// searching for the image
Action SearchImage= () => 
{
	tab.WaitDownloading();
	project.SendInfoToLog("Searching for the image", 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 there is the image
		if (!image.IsVoid)
		{
			// getting the image url
			if (!dynamicCaptcha) src = image.GetAttribute("src");
			imageString = image.DrawToBitmap(!dynamicCaptcha);
			timeout = false;
			break;
		}
 
		System.Threading.Thread.Sleep(waitTime); // waiting for element load
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// Recognition
Action Recognize= () => {
	project.SendInfoToLog("Recognition", 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];
};
 
//Input the answer
Action InputAnswer= () => 
{
	if (!String.IsNullOrEmpty(answer) && answer != "sorry")
	{
        project.SendInfoToLog("Input the answer and checking of correctness", 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(); //click to the image
				System.Threading.Thread.Sleep(500);// pause
			}
			if (fullAnswer) count++;
		}
 
		// searching for the button "Submit"
		HtmlElement apply = tab.FindElementById("recaptcha-verify-button");
		if (!apply.IsVoid) apply.Click();
 
		// checking correctness of the answer
		CheckOK();
		if (success) return;
 
		// input the other part of the answer
		if (fullAnswer)
		{
			for (int i = count; i < answer.Length; i++)
			{
				// searching for the picture again
				var testImage = tab.FindElementByAttribute("img", "class", "rc-image-tile", "regexp", 0);
				if (testImage.IsVoid) break;
				// getting the image url
				var newSrc = testImage.GetAttribute("src");
				// if the image has been changed, go out
				if (newSrc != src) break;
				else changed = true;
				// otherwise to continue the insertion
				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); // pause
					if (!apply.IsVoid) apply.Click();
					CheckOK();
					if (success) return;
				}
			}
		}
	}
	else answerIsEmpty = true;
};
 
//Input the answer
Action InputDynamicAnswer= () => 
{
	project.SendInfoToLog("Input the answer of dynamic captcha", 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) 
		{
			//click to the image
			he.Click();
			// pause
			System.Threading.Thread.Sleep(500);
		}
	}
 
	// pause
	System.Threading.Thread.Sleep(waitTime*2);
};
 
//Input the answer
Action InputDynamicAnswer2= () => 
{
	project.SendInfoToLog("Input the answer of dynamic captcha", 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) 
		{
			//click to the image
			he.Click();
			// pause
			System.Threading.Thread.Sleep(500);
		}
	}
 
	// pause
	System.Threading.Thread.Sleep(waitTime*2);
};
 
SearchReCaptcha2();
if (success)
	return "ok";
 
if (timeout) throw new Exception("Waiting time of element load is over");
 
for (int i = 0; i < tryRecognize; i++)
{
	project.SendInfoToLog(String.Format("Attempt №:{0}", i+1), needShowMessages);
 
	InputNotBotText();
	SearchTask();
	if (timeout) break;
 
	// Additional checking
	CheckOK();
	if (success) return "ok";
 
	int count = 0;
 
	// if captcha is dynamic
	if (dynamicCaptcha)
	{
		while (count < dynamicImagesRecognizeAttempts)
		{
			if (count > 0)
				System.Threading.Thread.Sleep(waitTime * 3); // waiting for load of disappearing images
 
			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("Waiting time of element load is over");
else throw new Exception("It has not been recognized. The recognition attempts has ended, before the answer has been counted");
 

Примечание

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

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

// waiting time
var waitTime = 3000;
// the number of recognition attempts
var tryRecognize = 10;
// the number of attempts to choose dynamic pictures
var dynamicImagesRecognizeAttempts = 20;
// the number of attempts to load the element
var tryLoadElement = 60;
// get the full answer
bool fullAnswer = false;
// show the messages about recognition progress
var needShowMessages = false;
// check correctness of the recognized answer
var needToCheck = true;

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

ru/addons/capmonster/rc2.txt · Последние изменения: 2017/07/31 14:25 — afameless