Search code examples
c#loopsselenium-webdriverocraspose

Selenium Loop Through Ocr Process until Captcha Image Text Solved


I am trying to solve a basic captcha image with Selenium Webdriver and Aspose Ocr. But Sometimes Ocr cannot read the image text right, so I need to repeat the process or create a loop until captcha solved.

Any idea how? I already tried the try-catch loop with while, but didn't get the expected result.

If captcha is entered correctly, it changes to css value to display none, otherwise it is display block and gives error message to indicate it was wrong.

Thanks in advance for the answers. I am not reputable to vote your answers, sorry for that too :))

My code is as follow:

ITakesScreenshot ssdriver = driver as ITakesScreenshot;
                byte[] screenshot = ssdriver.GetScreenshot().AsByteArray;
                MemoryStream ms = new MemoryStream(screenshot);
                IWebElement my_image = driver.FindElement(By.XPath("//*[@id=\"Captcha\"]/img"));

                Point point = my_image.Location;
                int width = my_image.Size.Width;
                int height = my_image.Size.Height;
                Rectangle section = new Rectangle(point, new Size(width, height));

                Bitmap originalScreenshot = (Bitmap)Bitmap.FromStream(ms);
                Bitmap final_image = CropImage(originalScreenshot, section);

                MemoryStream ms2 = new MemoryStream();
                final_image.Save(ms2, ImageFormat.Png);
                byte[] captchaimage = ms2.ToArray();
                Image image = Image.FromStream(ms2);
                OcrEngine ocrEngine = new OcrEngine();
                ocrEngine.Image = ImageStream.FromStream(ms2, ImageStreamFormat.Png);
                string SolvedCaptcha = "";
                if (ocrEngine.Process())
                {

                    string OcrCaptcha = ocrEngine.Text.ToString().Trim();
                    SolvedCaptcha = Regex.Replace(OcrCaptcha, "[^a-zA-Z0-9]", "").Trim();

                }
                IWebElement captcha = driver.FindElement(By.XPath("//*[@id=\"ContentPlaceHolder1_txtCaptcha\"]"));
                captcha.SendKeys(SolvedCaptcha);
                captcha.SendKeys(Keys.Enter);

Solution

  • I wrapped it in while block. Clear() didn't work for me so I needed to add js to to clear the input value before I set the upcoming one.It works for me this way, hope it helps to others. I couldn't use save captcha image version bc whenever I try to save it changes the image. So i went with taking a screenshot solution.

    while(driver.FindElement(By.Id("Captcha")).GetCssValue("display").ToString().Trim() == "block")
                        { 
                    ITakesScreenshot ssdriver = driver as ITakesScreenshot;
                    byte[] screenshot = ssdriver.GetScreenshot().AsByteArray;
                    MemoryStream ms = new MemoryStream(screenshot);
                    IWebElement my_image = driver.FindElement(By.XPath("//*[@id=\"Captcha\"]/img"));
    
                    Point point = my_image.Location;
                    int width = my_image.Size.Width;
                    int height = my_image.Size.Height;
                    Rectangle section = new Rectangle(point, new Size(width, height));
    
                    Bitmap originalScreenshot = (Bitmap)Bitmap.FromStream(ms);
                    Bitmap final_image = CropImage(originalScreenshot, section);
    
                    MemoryStream ms2 = new MemoryStream();
                    final_image.Save(ms2, ImageFormat.Png);
                    byte[] captchaimage = ms2.ToArray();
                    Image image = Image.FromStream(ms2);
                    image.Save(@"C:\Users\bulut\Desktop\testcaptcha.png");
                    OcrEngine ocrEngine = new OcrEngine();
                    ocrEngine.Image = ImageStream.FromStream(ms2, ImageStreamFormat.Png);
                    string SolvedCaptcha = "";
                    if (ocrEngine.Process())
                    {
    
                        string OcrCaptcha = ocrEngine.Text.ToString().Trim();
                        SolvedCaptcha = Regex.Replace(OcrCaptcha, "[^a-zA-Z0-9]", "").Trim();
    
                    }
                    var script = "document.getElementById('ContentPlaceHolder1_txtCaptcha').value = '';";
                    IWebElement element = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(script);
                    IWebElement captcha = driver.FindElement(By.XPath("//*[@id=\"ContentPlaceHolder1_txtCaptcha\"]"));
                    captcha.SendKeys(SolvedCaptcha);
                    captcha.SendKeys(Keys.Enter);
    
                        var wait5 = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
                        wait5.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete"));
                        Thread.Sleep(2000);
                }