2 回答
TA贡献1851条经验 获得超5个赞
您正在裁剪的元素图像不存在于代码截取的屏幕截图中。如果您放置调试并打印全屏截图路径并手动查看它,那么您可以看到要从图像中裁剪的所需元素不存在于其中。
因此,首先我们需要滚动页面以将所需元素带入视图,然后截取屏幕截图。然后我们需要根据元素的位置裁剪图像。
此外,
Point
类在给出元素的确切位置方面不是很可靠。其次,如果我们看到以下值
ImageIO.read(screenshot).getHeight() // ~ 943 => Total height
element.getSize().getHeight() // ~ 511 => Element height
point.getY() // ~ 743 => start top side y coordinate of element
所以我相信当从 x,y 绘制高度为 743 的矩形时,它超出了原始屏幕截图坐标。
所以我们需要在传递坐标的同时进行一些调整。
@Test
public void subImageTest() throws InterruptedException, IOException {
driver.get("http://learn-selenium-easy.blogspot.com/");
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,600)");
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
WebElement element=driver.findElement(By.xpath("//*[@id='PopularPosts1']"));
System.out.println(element.getSize());
// Take full screen screenshot
BufferedImage fullImg = ImageIO.read(screenshot);
ImageIO.read(screenshot).getHeight()
System.out.println(fullImg.getHeight());
System.out.println(fullImg.getWidth());
Point point = element.getLocation();
int elementWidth = element.getSize().getWidth();
int elementHeight = element.getSize().getHeight();
// Now no exception here
BufferedImage elementScreenshot= fullImg.getSubimage(220, 170,elementWidth+150,elementHeight+100);
// crop the image to required
ImageIO.write(elementScreenshot, "png", screenshot);
FileUtils.copyFile(screenshot, new File("C:\\Users\\AppData\\Local\\Temp\\mostread_screenshot.png"));//path to save screen shot
}
程序执行后元素的最终子图像
TA贡献1906条经验 获得超3个赞
RasterFormat异常
根据Java Docs,如果 Raster中存在无效的布局信息,则会抛出RasterFormatException。
获取位置()
根据Selenium 文档 返回包含元素左上角getLocation()
位置的点。
获取子图像()
根据Java Docs getSubimage()
返回由指定矩形区域定义的子图像。返回的 BufferedImage 与原始图像共享相同的数据数组,定义为:
getSubimage
public BufferedImage getSubimage(int x,
int y,
int w,
int h)
Returns a subimage defined by a specified rectangular region. The returned BufferedImage shares the same data array as the original image.
Parameters:
x - the X coordinate of the upper-left corner of the specified rectangular region
y - the Y coordinate of the upper-left corner of the specified rectangular region
w - the width of the specified rectangular region
h - the height of the specified rectangular region
Returns:
a BufferedImage that is the subimage of this BufferedImage.
Throws:
RasterFormatException - if the specified area is not contained within this BufferedImage.
我已经采用了您自己的代码,添加了几System.out.println()行来展示到底出了什么问题。
代码块:
public class A_demo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
WebDriver driver = new ChromeDriver(options);
driver.get("http://learn-selenium-easy.blogspot.com/");
// Xpath of element to take screen shot
WebElement element=driver.findElement(By.xpath("//*[@id='PopularPosts1']"));
System.out.println("Element size is:"+element.getSize());
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshot, new File("./Screenshots/mostread_TakesScreenshot.png")); //path to save screen shot
// Take full screen screenshot
BufferedImage fullImg = ImageIO.read(screenshot);
Point point = element.getLocation();
System.out.println("Co-ordinates where on the page is the top left-hand corner of the rendered element:"+point);
int elementWidth = element.getSize().getWidth();
System.out.println("Element width is:"+elementWidth);
int elementHeight = element.getSize().getHeight();
System.out.println("Element height is:"+elementHeight);
BufferedImage elementScreenshot= fullImg.getSubimage(point.getX(), point.getY(), elementWidth,elementHeight); //exception here
// crop the image to required
ImageIO.write(elementScreenshot, "png", screenshot);
FileUtils.copyFile(screenshot, new File("./Screenshots/mostread_BufferedImage.png"));//path to save screen shot
}
}
控制台输出:
INFO: Detected dialect: W3C
Element size is:(340, 486)
Co-ordinates where on the page is the top left-hand corner of the rendered element:(104, 744)
Element width is:340
Element height is:486
Exception in thread "main" java.awt.image.RasterFormatException: (y + height) is outside of Raster
at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
at java.awt.image.BufferedImage.getSubimage(Unknown Source)
at demo.A_demo.main(A_demo.java:78)
解释
如前所述,根据您的代码块,fullImg.getSubimage()
将尝试返回一个BufferedImage
ie elementScreenshot,这将是一个由矩形区域指定的子图像:
x:指定矩形区域左上角的X坐标 -
point.getX()
- 104y:指定矩形区域左上角的Y坐标 -
point.getY()
- 744w:指定矩形区域的宽度 - elementWidth - 340
h:指定矩形区域的高度 - elementHeight - 486
因此,预期的高度BufferedImage
变成了744
+ 486
= 1230
,这几乎超出了Raster 的范围。因此您会看到错误。
解决方案
要截取特定元素或特定 div 使用硒和爪哇您可以在使用Selenium Java Client v3.14.0、ChromeDriver v2.41、Chrome v 68.0AShot()
时使用导入ashot-1.4.4.jar的方法。
注意:来自ashot-1.4.4.jar 的
AShot()
方法仅适用于启用jQuery的Web 应用程序。
代码块:
import ru.yandex.qatools.ashot.AShot;
import ru.yandex.qatools.ashot.Screenshot;
public class A_demo
{
public static void main(String[] args) throws Exception
{
System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.addArguments("disable-infobars");
WebDriver driver = new ChromeDriver(options);
driver.get("http://learn-selenium-easy.blogspot.com/");
WebElement myWebElement = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='PopularPosts1']")));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", myWebElement);
Screenshot myScreenshot = new AShot().takeScreenshot(driver, myWebElement);
ImageIO.write(myScreenshot.getImage(),"PNG",new File("./Screenshots/elementAShotScreenshot.png"));
driver.quit();
}
}
添加回答
举报