[英]How to find an element by image
眾所周知, 硒支持多種定位器策略以在網頁上查找元素。
但是我的要求是不同的,我有一些站點,其中硒支持的任何定位器不足以唯一地找到元素。
由於硒提供了創建自己的自定義定位器策略來查找元素的便利 ,我正在嘗試創建圖像定位器,它可以像使用appium一樣使用子圖像的base64 String
來查找元素。
圖像定位器的要點:
為了完成此任務,我將創建自定義Image
定位器,如下所示:
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>"))
我能做到的一切,除了一個更好的庫來檢測的精確坐標subimage
從image
找到使用坐標的元素。
有人可以建議我一種更好的方法來完成此任務嗎?
您可以選擇不同的選項,例如:
正如@Dmitri所建議的那樣,我將使用OpenCV的Java綁定 。
下載適當的OpenCV並將其解壓縮到classpath
然后嘗試獲取坐標為:
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);
希望對大家有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.