ZennoLab

Automate everything

User Tools

Site Tools


Sidebar

Translations of this page:

en:addons:capmonster:rc-associations

ReCaptcha Associations



CapMonster 2 starting from 2.6.0.0 allows to recognize ReCaptcha with words and phrases associations using special module ZennoLab.ReCaptchaAssociation.

Here is the example of this captcha:

You should send captcha with associations to CapMonster 2 with the following parameters:
“Task=category:variant1;variant2…&CapMonsterModule=ZennoLab.ReCaptchaAssociation”

Example:
“Task=sugar:pickup;design element;…;maltose&CapMonsterModule=ZennoLab.ReCaptchaAssociation”

As answer to this catpcha, CapMonster 2 will return matching variants of associations separated with “;”

Using in ZennoPoster

To send recaptcha with associations to *CapMonster 2** you should use the following snippet:

//Main settings
 
// waiting timeout
var waitTime = 1000;
// recognition attempts
var tryRecognize = 3;
// attempts to load element
var tryLoadElement = 60;
// show recognizing progress messages
var needShowMessages = false;
// need to check answer's correctness
var needToCheck = true;
// count of associations need to click in task with associations
var countAssociations = 4;
 
// Additional variables
 
// tab
var tab = instance.ActiveTab;
// congratulations, you are not robot
var success = false;
// audio file
var file = string.Empty;
// file has been deleted
var fileDeleted = true;
// answer to audio captcha
var answer = string.Empty;
// new type ReCaptcha2
var isNewView = true;
// ReCaptcha 1
var isRecaptcha1 = false;
// timeout exceeded 
var timeout = false;
// error loading file
var fileLoadingError = false;
var usedURLs = new List<string>();
// task with associations
var isAssociationsTask = false;
var isFirstAttempt = true;
var coincidenceReCaptcha2Index = -1;
 
 
Action FindAssociations= () => {
	// getting task
	var associationsTask = tab.FindElementByAttribute("div", "class", "rc-text-desc-wrapper", "regexp", 0);
	if (!associationsTask.IsVoid)
	{
		var phraseSplit = associationsTask.GetAttribute("innerhtml").Split(new []{"<span>", "</span>"}, StringSplitOptions.None);
		if (phraseSplit.Length == 3)
		{
			var phrase = phraseSplit[1];
			if (phrase != string.Empty)
			{
				var table = tab.FindElementByAttribute("table", "class", "rc-text-choices", "text", 0);
				if (!table.IsVoid)
				{
					var tableElems = table.FindChildrenByTags("td");
 
					if (tableElems.Count > 0)
					{
						var variants = new Dictionary<string, HtmlElement>();
						var words = new List<string>();
						foreach(var elem in tableElems)
						{
							var text = elem.GetAttribute("innertext");
							variants.Add(text, elem);
							words.Add(text);
						}
 
						project.SendInfoToLog("Recognizing text task", needShowMessages);
 
						var requestString = string.Format("{0}:{1}", phrase, string.Join(";", words));
 
						var imageStr = Convert.ToBase64String(new Byte[0]);
 
						var rc = ZennoPoster.CaptchaRecognition("CapMonster2.dll", imageStr , string.Format("Task={0}&CapMonsterModule=ZennoLab.ReCaptchaAssociation", requestString));
						var cmAnswer = rc.Split(new [] {"-|-"}, StringSplitOptions.RemoveEmptyEntries)[0];
						if (string.IsNullOrEmpty(cmAnswer) || cmAnswer == "sorry")
						{
							var reload = tab.FindElementByAttribute("div", "id", "recaptcha-reload-button", "regexp", 0);
							if (!reload.IsVoid)
								reload.Click();
							return;
						}
 
						var answers = cmAnswer.Split(new []{";"}, StringSplitOptions.None);
 
						for (int i = 0; i < countAssociations; i++)
						{
							if (i < answers.Length)
							{
								variants[answers[i]].Click();
								System.Threading.Thread.Sleep(500); //pause
							}
						}
					}
				}
			}
		}
	}
};
 
// Searching audio button element
Action TryOpenAudioForm = () => {
	for (int k = 0; k < tryLoadElement; k++)
	{
		var audioButton = tab.FindElementByAttribute("div", "id", "recaptcha-audio-button", "regexp", 0);
		// if found
		if (!audioButton.IsVoid)
		{
			// press button
			audioButton.Click();
			tab.WaitDownloading();
			break;
		}
		System.Threading.Thread.Sleep(waitTime); // pause
		if (k == (tryLoadElement - 1)) timeout = true;
	}
	System.Threading.Thread.Sleep(waitTime); // pause
};
 
Action OpenAudioTask= () => {
	project.SendInfoToLog("Loading audio task", needShowMessages);
	if (isNewView)
	{
		//checking task type in the form
		var task = tab.FindElementByAttribute("div", "class", "rc-imageselect-desc-wrapper", "regexp", 0);
		if (!task.IsVoid) TryOpenAudioForm(); // graphic task has been found, then loading audio
	}
	else
	{
		var elem = tab.FindElementByAttribute("input:submit", "class", @"fbc-button-audio\ fbc-button", "regexp", 0);
		if (!elem.IsVoid) elem.Click();	
 
		tab.WaitDownloading();
		var errorElem = tab.FindElementByAttribute("div", "class", "fbc-message", "regexp", 0);
		if (!errorElem.IsVoid)
		{
			var attr = errorElem.GetAttribute("innertext");
			if (attr.Contains("Please enable JavaScript and/or update your browser to get an audio challenge"))
			{
				throw new Exception("Can't open audio form, try to change userAgent");
			}
		}
	}
};
 
Action VisibleIndexReCaptchaDefinition= () => {
	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)
			{
				coincidenceReCaptcha2Index = i;
				break;
			}
		}
	}
};
 
// Identifying ReCaptcha version
Action NotRobotClick= () => {
	for (int k = 0; k < tryLoadElement; k++)
	{
		// searching coincidence index of recaptcha elements
		VisibleIndexReCaptchaDefinition();
		if (coincidenceReCaptcha2Index < 0)
			continue;
 
		// searching "I'm not robot" checkbox
		var notRobot = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
		// if found
		if (!notRobot.IsVoid)
		{
			// checking checkbox
			notRobot.Click();
			// pause
			System.Threading.Thread.Sleep(waitTime);
 
			// if entering captcha is not required
			var check = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", 0);
			if (!check.IsVoid)
			{
				if (check.OuterHtml.Contains("style=\"\""))
				{
					success = true;
					break;
				}
			}
 
			// waiting when form will be loaded
			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); // waiting when element will be loaded
				if (j == (tryLoadElement - 1)) timeout = true;
			}
			break;
 
		}
		else
		{
			// checking if ReCaptcha 1 audio button exists
			HtmlElement r1 = tab.FindElementById("recaptcha_switch_audio");
			if (!r1.IsVoid)
			{
				r1.Click();
				isRecaptcha1 = true;
				break;
			}
 
			// checking ReCaptcha2 type
			var elem = tab.FindElementByAttribute("input:submit", "class", @"fbc-button-audio\ fbc-button", "regexp", 0);
			if (!elem.IsVoid)
			{
				isNewView = false;
				break;
			}
			System.Threading.Thread.Sleep(waitTime); //pause
		}
		if (k == (tryLoadElement - 1)) timeout = true;
	}
};
 
// Downloading mp3 file
Action GetAudioFile= () => {
 
	var href = String.Empty;
 
	// getting audio task
	for (int k = 0; k < tryLoadElement; k++)
	{
		if (isRecaptcha1)
		{
			var audioChallenge = tab.FindElementByAttribute("a", "id", "recaptcha_audio_download", "text", 0);
			// if found, getting link to audio file
			if (!audioChallenge.IsVoid)
			{
				href = audioChallenge.GetAttribute("href");
				break;
			}
			else System.Threading.Thread.Sleep(waitTime);
		}
		else
		{
			if (isNewView)
			{
				if (isFirstAttempt)
				{
					isFirstAttempt = false;
				}
				else
				{
					var reload = tab.FindElementByAttribute("div", "id", "recaptcha-reload-button", "regexp", 0);
					if (!reload.IsVoid)
					{
						reload.Click();
						tab.WaitDownloading();
					}
				}
 
				var audioChallenge = tab.FindElementByAttribute("a", "class", "rc-audiochallenge-download-link", "regexp", 0);
				// if found, getting link to audio file
				if (!audioChallenge.IsVoid)
				{
					href = audioChallenge.GetAttribute("href");
					isAssociationsTask = false;
					break;
				}
				else
				{
					isAssociationsTask = true;
					return;
				}
				System.Threading.Thread.Sleep(waitTime); // waiting when form will be loaded
			}
			else
			{
				var audioChallenge = tab.FindElementByAttribute("audio", "class", "fbc-audio-controls", "regexp", 0);
				// if found, getting link to audio file
				if (!audioChallenge.IsVoid)
				{
					href = audioChallenge.FindChildByAttribute("source", "src", ".mp3", "text", 0).GetAttribute("src");
					href = "https://www.google.com" + href;
					break;
				}
				else System.Threading.Thread.Sleep(waitTime); // waiting when element will be loaded
			}
		}
		if (k == (tryLoadElement - 1)) timeout = true;
	}
 
	foreach (var usedUrl in usedURLs)
	{
		if (usedUrl.Contains(href))
			throw new Exception("new audio file is absent");
	}
	usedURLs.Add(href);
 
	project.SendInfoToLog("Downloading audio file", needShowMessages);
	try
	{
		var proxy = instance.GetProxy();
		var respType = ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.File;
		var timeoutRequest = 30000;
		var cookies = instance.GetCookie("google.com", true);
		var userAgent = project.Profile.UserAgent;
		var maxRedirectCount = 1;
		var downloadPath = project.Directory + "\\audiofiles";
		file = ZennoPoster.HttpGet(href, proxy, "UTF8", respType, timeoutRequest, cookies, userAgent, false, maxRedirectCount, null, downloadPath);
		fileDeleted = false;
	}
	catch (Exception ex)
	{
		throw new Exception("Failed to download audio file");
	}
};
 
Action Recognize= () => {
	project.SendInfoToLog("Recognizing", needShowMessages);
	try 
	{
		if (!File.Exists(file)) 
		{
			fileLoadingError = true;
			fileDeleted = true;
			return;
		}
		var bytes = File.ReadAllBytes(file);
		if (bytes.Length < 1024)
		{
			fileLoadingError = true;
			return;
		}
		string str = Convert.ToBase64String(bytes);
		var rc = ZennoPoster.CaptchaRecognition("CapMonster2.dll", str, "CapMonsterModule=ZennoLab.AudioReCaptcha&ParallelMode=true");
		var split = rc.Split(new [] {"-|-"}, StringSplitOptions.RemoveEmptyEntries);
		if (split.Length > 0)
			answer = split[0];
        if (answer.Contains("133193320491090004119440")) throw new Exception("Your IP was banned!");
	} 
	finally 
	{
	    if (File.Exists(file)) 
	    {
			File.Delete(file);
			fileDeleted = true;
        }
	}
};
 
Action InputAnswer= () => {
	if (!String.IsNullOrEmpty(answer) && answer != "sorry")
	{
		project.SendInfoToLog("Inserting answer", needShowMessages);
		HtmlElement audioAnswerInput = null;
		// searching answer input field
		if (isRecaptcha1)
		{
			audioAnswerInput = tab.FindElementByAttribute("input:text", "id", "recaptcha_response_field", "text", 0);
		}
		else
		{
			if (isNewView) audioAnswerInput = tab.FindElementByAttribute("input:text", "id", "audio-response", "regexp", 0);
			else audioAnswerInput = tab.FindElementByAttribute("input:text", "id", "response", "text", 0);
		}
 
		// if found
		if (!audioAnswerInput.IsVoid)
		{
			// inserting answer
			audioAnswerInput.SetValue(answer, "None", false);
		}
 
		// pause
		System.Threading.Thread.Sleep(waitTime);
	}
	else throw new Exception("Answer not received");
};
 
// Verifying
Action SubmitAnswer= () => {
	// searching "Verify" button
	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();
	tab.WaitDownloading();
 
	// pause
	System.Threading.Thread.Sleep(waitTime);
};
 
// Checking if answer is correct for old ReCaptcha
Action CheckOldView= () => {
	// checking if there is recognition mistake
	HtmlElement he = tab.GetDocumentByAddress("0;_0").FindElementByTag("form", 0).FindChildByAttribute("div", "class", "fbc-error", "regexp", 0);
	if (!he.IsVoid) 
	{
		return;
	}
 
	string txt = string.Empty;
	// searching text to insert
	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); // pause
			continue;
		}
		if (k == (tryLoadElement - 1)) timeout = true;
	}
 
	// searching where to insert text
	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); // pause
			continue;
		}
		if (k == (tryLoadElement - 1)) timeout = true;
	}
 
	// pressing "Verify"
	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); // pause
			continue;
		}
		if (k == (tryLoadElement - 1)) timeout = true;
	}
	success = true;
};
 
// Checking if answer is correct for ReCaptcha 2
Action Check= () => {
	project.SendInfoToLog("Verifying answer", needShowMessages);
	for (int k = 0; k < tryLoadElement; k++)
	{
		var checkAnswer = tab.FindElementByAttribute("div", "class", "recaptcha-checkbox-checkmark", "regexp", coincidenceReCaptcha2Index);
		if (!checkAnswer.IsVoid)
		{
			if (checkAnswer.OuterHtml.Contains("style=\"\""))
				success = true;
			else
				success = false;
			return;
		}
		if (k == (tryLoadElement - 1)) timeout = true;
		System.Threading.Thread.Sleep(waitTime);
	}
};
 
// Checking "I'm not robot" checkbox
NotRobotClick();
if (success) return "ok";
 
// trying to recognize ReCaptcha
for (int i = 0; i < tryRecognize; i++)
{
	if (!isRecaptcha1) OpenAudioTask();
	if (timeout) break;
	GetAudioFile();
	if (timeout) break;
 
	if (isAssociationsTask)
	{
		FindAssociations();
	}
	else
	{
		Recognize();
		if (fileLoadingError) 
		{
			fileLoadingError = false;
			continue;
		}
		if (timeout) break;
		InputAnswer();
		if (timeout) break;
		if (!fileDeleted)
		{
			if (File.Exists(file))
			{
				File.Delete(file);
				fileDeleted = true;
			}
		}
 
		if (isRecaptcha1) return "ok";
	}
	SubmitAnswer();
 
	if (!needToCheck) return "ok";
 
	if (timeout) break;
	if (!isNewView) CheckOldView();
	else Check();
	if (success) return "ok";
}
 
if (timeout) throw new Exception("Loading element timeout is exceeded");
else throw new Exception("Not recognized, Attempts to recognize were ended, before the response was received");

NOTE

You are able to set maximum number of correct answers, changhing value of the snippet variable below:

var countAssociations = 4;
en/addons/capmonster/rc-associations.txt · Last modified: 2021/01/23 21:14 by sergodjan