Javascript 如何通过图像查找元素
正如我们所知,支持多定位器策略来查找网页上的元素 但我的要求不同,我有一些站点,其中由selenium支持的任何定位器都不足以唯一地找到元素 由于selenium提供了创建自己的自定义定位器策略来查找元素的功能,因此我正在尝试创建图像定位器,它可以使用子图像的base64字符串查找元素 图像定位器的点: 使用URL启动浏览器 捕获页面的屏幕截图 从屏幕截图中检测子图像的x、y位置 使用页面中的x,y位置查找元素 为了完成此任务,我正在创建自定义图像定位器,如下所示:Javascript 如何通过图像查找元素,javascript,java,selenium,selenium-webdriver,groovy,Javascript,Java,Selenium,Selenium Webdriver,Groovy,正如我们所知,支持多定位器策略来查找网页上的元素 但我的要求不同,我有一些站点,其中由selenium支持的任何定位器都不足以唯一地找到元素 由于selenium提供了创建自己的自定义定位器策略来查找元素的功能,因此我正在尝试创建图像定位器,它可以使用子图像的base64字符串查找元素 图像定位器的点: 使用URL启动浏览器 捕获页面的屏幕截图 从屏幕截图中检测子图像的x、y位置 使用页面中的x,y位置查找元素 为了完成此任务,我正在创建自定义图像定位器,如下所示: public class B
public class ByImage extends By {
String imageBase64String
/**
* @param imageBase64String
*/
public ByImage(String imageBase64String) {
this.imageBase64String = imageBase64String
}
@Override
public List<WebElement> findElement(SearchContext context) {
List<WebElement> els = findElements(context)
if (els) {
return els.get(0)
}
throw new NoSuchElementException("Element not found")
}
@Override
public List<WebElement> findElements(SearchContext context) {
//Get current screenshot
byte[] screenshotByte = ((TakesScreenshot)context).getScreenshotAs(OutputType.BYTES))
byte[] subImgToFindByte = DatatypeConverter.parseBase64Binary(imageBase64String)
//Convert buffred image to get height and width of subimage
BufferedImage bufferedSubImgToFind = ImageIO.read(new ByteArrayInputStream(subImgToFindByte ));
//Here I need a mechanism to get coordinates of sub image from screenshot
//Suppose I able to find x, y
double x
double y
//Now find element using coordinates
//Now calculate center point
int centerX = int(x + (bufferedSubImgToFind.getWidth() / 2))
int centerY = int(y + (bufferedSubImgToFind.getHeight() / 2))
JavascriptExecutor js = ((JavascriptExecutor)context)
return js.executeScript("return document.elementsFromPoint(arguments[0], arguments[1]);", centerX, centerY)
}
}
现在,测试用例如下所示:
WebDriver driver = new ChromeDriver()
driver.get("<URL>")
WebElement elementByImage = driver.findElement(new ByImage("<Base64 String of the subimage>"))
我能够实现所有功能,除了一个更好的库,可以从图像中检测子图像的精确坐标,并使用坐标查找元素
有谁能给我一个更好的方法来完成这项任务吗?你可以选择不同的方法,比如: 您可以使用以在主屏幕截图中查找子图像,查看文章以获得全面的解释和代码片段。 提供一些用于图像识别/交互的简单API 为图像模板提供图像识别和模式实现
正如@Dmitri建议的那样,我要和他一起去 并将其提取到类路径中,并尝试获取坐标,如下所示:
import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
byte[] screenshotByte = ((TakesScreenshot)context).getScreenshotAs(OutputType.BYTES))
byte[] subImgToFindByte = DatatypeConverter.parseBase64Binary(imageBase64String)
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat source = Imgcodecs.imdecode(new MatOfByte(screenshotByte), Imgcodecs.IMREAD_UNCHANGED);
Mat template = Imgcodecs.imdecode(new MatOfByte(subImgToFindByte), Imgcodecs.IMREAD_UNCHANGED);
int result_cols = source.cols() - template.cols() + 1;
int result_rows = source.rows() - template.rows() + 1;
Mat outputImage = new Mat(result_rows, result_cols, CvType.CV_32FC1);
// Template matching method
Imgproc.matchTemplate(source, template, outputImage, Imgproc.TM_SQDIFF_NORMED);
MinMaxLocResult mmr = Core.minMaxLoc(outputImage);
// Now get the point
Point point = mmr.minLoc;
double x = point.x;
double y = point.y;
//Now get the find the element using x, y after calculating center point.
int centerX = int(x + (bufferedSubImgToFind.getWidth() / 2));
int centerY = int(y + (bufferedSubImgToFind.getHeight() / 2));
WebElement el = js.executeScript("return document.elementFromPoint(arguments[0], arguments[1]);", centerX, centerY);
希望对大家都有帮助。在图像标签的src中找不到图像名称或类似信息?请发布一些相同的HTML以便我们可以看到。你知道这张照片的大小吗?如果你能在页面的大屏幕截图中找到它,你必须知道它的一些细节。你知道什么?@JeffC我只是想创建一个自定义定位器,它可以使用image base64 string查找元素,在这种情况下,我们只需要使用任何工具捕获特定元素的屏幕截图,并将其转换为base64 string,然后将其传递给此自定义定位器,在这个自定义定位器中,它获取当前可见页面的屏幕截图,并尝试使用OpenCV之类的库从屏幕截图中查找子图像。现在,如果用户从大屏幕截图并尝试在小屏幕上查找,则大小将很重要,在这种情况下,我们可以简单地用页面的当前屏幕截图缩放子图像,以便轻松获得正确的坐标。这是我试图实现的一个基于图像的通用解决方案,这就是为什么我们不需要任何HTML。。谢谢@为了更好的理解,请看这里。这是appium教程,appium正在做我想在web上做的事情