Javascript 如何通过图像查找元素

Javascript 如何通过图像查找元素,javascript,java,selenium,selenium-webdriver,groovy,Javascript,Java,Selenium,Selenium Webdriver,Groovy,正如我们所知,支持多定位器策略来查找网页上的元素 但我的要求不同,我有一些站点,其中由selenium支持的任何定位器都不足以唯一地找到元素 由于selenium提供了创建自己的自定义定位器策略来查找元素的功能,因此我正在尝试创建图像定位器,它可以使用子图像的base64字符串查找元素 图像定位器的点: 使用URL启动浏览器 捕获页面的屏幕截图 从屏幕截图中检测子图像的x、y位置 使用页面中的x,y位置查找元素 为了完成此任务,我正在创建自定义图像定位器,如下所示: public class B

正如我们所知,支持多定位器策略来查找网页上的元素

但我的要求不同,我有一些站点,其中由selenium支持的任何定位器都不足以唯一地找到元素

由于selenium提供了创建自己的自定义定位器策略来查找元素的功能,因此我正在尝试创建图像定位器,它可以使用子图像的base64字符串查找元素

图像定位器的点:

使用URL启动浏览器 捕获页面的屏幕截图 从屏幕截图中检测子图像的x、y位置 使用页面中的x,y位置查找元素 为了完成此任务,我正在创建自定义图像定位器,如下所示:

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上做的事情