如何使用Selenium WebDriver和Java从图像(validation码)中读取文本

我有注册网页,但在最后validation码显示..

我无法从图像中读取文本。 我要提一下代码和输出..

@Test public void loginTest() throws InterruptedException { System.out.println("Testing"); driver.get("https://customer.onlinelic.in/ForgotPwd.htm"); WebElement element = driver.findElement(By.xpath("//*[@id='forgotPassword']/table/tbody/tr[5]/td[3]/img")); System.out.println(" get the instance "); String elementTest = element.getAttribute("src"); System.out.println("Element : " + elementTest); } 

输出:错误

线程“main”中的exceptionorg.openqa.selenium.NoSuchElementException:无法定位元素:{“method”:“xpath”,“selector”:“// [@ id =’forgotPassword’] / table / tbody / tr [ 5] / td [3] / img“}命令持续时间或超时:60.02秒有关此错误的文档,请访问: http ://seleniumhq.org/exceptions/no_such_element.html构建信息:版本:’2.35.0′ ,修订版:’8df0c6b’,时间:’2013-08-12 15:43:19’系统信息:os.name:’Windows 7’,os.arch:’amd64’,os.version:’6.1’,java .version:’1.6.0_26’会话ID:5f5b2e1a-56a4-49ad-8fd3-2870747a7768驱动信息:org.openqa.selenium.firefox.FirefoxDriverfunction[{platform = XP,acceptSslCerts = true,javascriptEnabled = true,browserName = firefox ,rotate = false,locationContextEnabled = true,version = 23.0.1,cssSelectorsEnabled = true,databaseEnabled = true,handlesAlerts = true,browserConnectionEnabled = true,nativeEvents = true,webStorageEnabled = true,applicationCacheEnabled = true,takesScreenshot = true}] at sun .reflect.NativeConstructorAccessorI mpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)at java.lang.reflect.Constructor.newInstance(Constructor。 java:513)org.openqa.selenium.remote.Atote.Error.andn.OnRaponse.Arn上的org.openqa.selenium.remote.Error.Arn .rmoteWebDriver.execute(RemoteWebDriver.java:554)org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:307)atg.openqa.selenium.remote.RemoteWebDriver.findElementByXPath(RemoteWebDriver.java:404)at at org.openqa.selenium.By $ ByXPath.findElement(By.java:344)org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:299)at seleniumtest.CaptchaTest.loginTest(CaptchaTest.java:41)在seleniumtest.CaptchaTest.main(CaptchaTest.java:59)引起:org.openq a.selenium.remote.ErrorHandler $ UnknownServerException:无法找到元素:{“method”:“xpath”,“selector”:“// [@ id =’forgotPassword’] / table / tbody / tr [5] / td [3] / img“}构建信息:版本:’2.35.0’,修订版:’8df0c6b’,时间:’2013-08-12 15:43:19’系统信息:os.name:’Windows 7’, os.arch:’amd64’,os.version:’6.1’,java.version:’1.6.0_26’驱动程序信息:driver.version:未知.FirefoxDriver.prototype.findElementInternal_(file:/// C:/ Users /lukup/AppData/Local/Temp/anonymous4043037924964932185webdriver-profile/extensions/fxdriver@googlecode.com/components/driver_component.js:8880)at .fxdriver.Timer.prototype.setTimeout / <.notify(file:/// C: /Users/lukup/AppData/Local/Temp/anonymous4043037924964932185webdriver-profile/extensions/fxdriver@googlecode.com/components/driver_component.js:396)

只是为了详细解释以前的答案,CAPTCHA作为“完全自动公共图灵测试告诉计算机和人类分开”的首字母缩写。 所以,如果“机器”可以解决它,它并不是真正做到的。

为了解决这个问题,您可以采取一些措施 – 使用外部服务的API,例如http://www.deathbycaptcha.com 。 您实现他们的API,将CAPTCHA传递给他们并获得文本。 我观察到的平均解算时间约为10-15秒。

实施示例(取自此处 )

 import com.DeathByCaptcha.AccessDeniedException; import com.DeathByCaptcha.Captcha; import com.DeathByCaptcha.Client; import com.DeathByCaptcha.SocketClient; import com.DeathByCaptcha.HttpClient; /* Put your DeathByCaptcha account username and password here. Use HttpClient for HTTP API. */ Client client = (Client)new SocketClient(username, password); try { double balance = client.getBalance(); /* Put your CAPTCHA file name, or file object, or arbitrary input stream, or an array of bytes, and optional solving timeout (in seconds) here: */ Captcha captcha = client.decode(captchaFileName, timeout); if (null != captcha) { /* The CAPTCHA was solved; captcha.id property holds its numeric ID, and captcha.text holds its text. */ System.out.println("CAPTCHA " + captcha.id + " solved: " + captcha.text); if (/* check if the CAPTCHA was incorrectly solved */) { client.report(captcha); } } } catch (AccessDeniedException e) { /* Access to DBC API denied, check your credentials and/or balance */ } 

两个问题。

  1. 您有错误的xpath,因此您获得NoSuchElementexception。

  2. 即使你有正确的xpath,你也无法提取文本,因为如果CAPTCHA会破坏这一点

CAPTCHA的全部目的是阻止UI的自动化! 您可能希望使用内部API来validation操作。

我有一个适用于特定网站的解决方案。 您可以获得整个页面的快照并获取validation码的图像。 然后将validation码图像的整个宽度除以总字符数(在validation码中通常它通常是常数)。 现在我们有了validation码图像的各个字符。 通过重新加载页面来收集validation码的所有可能字符。

一旦你拥有了所有可能的角色,然后给出任何validation码图像,你可以将它的角色与我们拥有的图像进行比较,并决定它是哪个字母或数字。

要遵循的步骤:

  1. 收集validation码图像并将其划分为单个字符。

     private static BufferedImage cropImage(File filePath, int x, int y, int w, int h) { try { BufferedImage originalImgage = ImageIO.read(filePath); BufferedImage subImgage = originalImgage.getSubimage(x, y, w, h); return subImgage; } catch (IOException e) { e.printStackTrace(); return null; } } 
    1. 将所有可能的图像保存在文件夹中 在此处输入图像描述

    2. 现在读取validation码的每个字符图像,并将其与上述文件夹中的所有其他图像进行比较。 您可以使用像素值比较两个图像public static float getDiff(File f1,File f2,int width,int height)throws IOException {BufferedImage bi1 = null; BufferedImage bi2 = null; bi1 = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB); bi2 = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);

        bi1 = ImageIO.read(f1); bi2 = ImageIO.read(f2); float diff = 0; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int rgb1 = bi1.getRGB(i, j); int rgb2 = bi2.getRGB(i, j); int b1 = rgb1 & 0xff; int g1 = (rgb1 & 0xff00) >> 8; int r1 = (rgb1 & 0xff0000) >> 16; int b2 = rgb2 & 0xff; int g2 = (rgb2 & 0xff00) >> 8; int r2 = (rgb2 & 0xff0000) >> 16; diff += Math.abs(b1 - b2); diff += Math.abs(g1 - g2); diff += Math.abs(r1 - r2); } } return diff; } 
  2. 任何具有较少diff值的图像是实际匹配。 将其名称附加到字符串。
  3. 读完validation码返回字符串1的所有图像后: https : //i.stack.imgur.com/FYPhd.png

在上图中,图像名称指定数字或字符。

这仅适用于像[ 在此处输入图像描述 1

在此处输入图像描述

以下是从上图中读取文本的示例代码:

 import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.asprise.util.ocr.OCR; public class ExtractImage { WebDriver driver; @BeforeTest public void setUpDriver() { driver = new FirefoxDriver(); } @Test public void start() throws IOException{ /*Navigate to http://www.mythoughts.co.in/2013/10/extract-and-verify-text-from-image.html page * and get the image source attribute * */ driver.get("http://www.mythoughts.co.in/2013/10/extract-and-verify-text-from-image.html"); String imageUrl=driver.findElement(By.xpath("//*[@id='post-body-5614451749129773593']/div[1]/div[1]/div/a/img")).getAttribute("src"); System.out.println("Image source path : \n"+ imageUrl); URL url = new URL(imageUrl); Image image = ImageIO.read(url); String s = new OCR().recognizeCharacters((RenderedImage) image); System.out.println("Text From Image : \n"+ s); System.out.println("Length of total text : \n"+ s.length()); driver.quit(); /* Use below code If you want to read image location from your hard disk * BufferedImage image = ImageIO.read(new File("Image location")); String imageText = new OCR().recognizeCharacters((RenderedImage) image); System.out.println("Text From Image : \n"+ imageText); System.out.println("Length of total text : \n"+ imageText.length()); */ } } 

以下是上述程序的输出:

图像源路径: http : //2.bp.blogspot.com/-42SgMHAeF8U/Uk8QlYCoy-I/AAAAAAAADSA/TTAVAAgDhio/s1600/love.jpg

从来没有M2使用O,ne喜欢你永远不会说忙,一个需要你永远不会欺骗那个让你信任的人,永远不会让那个Zways记得你的人。

总文字长度:175

忘记密码表单位于iframe中。 这就是selenium没有找到元素的原因。 您需要先切换到保存表单的iframe,然后运行您的findelement。 你的xpath是正确的。

使用driver.switchTo().frame(arg0)切换到帧。 在这里查看javadoc

为了获得validation码文本,我不明白你的意思是“存储测试和比较”。 理想情况下,您不应该从validation码中读取文本(正如其他人所提到的)。 我看到的一种替代方法是将captcha值存储为开发和QA环境中的alt text 。 这样您就可以阅读它并输入文本框。 当代码进入生产环境或任何外部环境时,可以删除此alt text

对于简单的validation码,您可以调用免费的ocr.space在线OCR服务。 只要这只是一个文本有点扭曲的图像就可以了。 您也可以使用Google Cloud Vision OCR ,它同样运行良好,但设置起来有点复杂。

人们无法从CAPTCHA中读到。 如果您可以从CAPTCHA阅读,那么使用CAPTCHA是没有意义的。