Java+Selenium根據元素創建指定區域截圖——Element快照
執行步驟
獲取全屏的截圖
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
BufferedImage image = ImageIO.read(screen);
獲取element的寬高以及坐標
創建一個WebElement元素,並且獲取元素的高度,寬度,坐標信息
並且使用元素的高度和寬度創建一個矩形
WebElement element = driver.findElement(By.id("su"));
//獲取元素的高度、寬度
int width = element.getSize().getWidth();
int height = element.getSize().getHeight();
//創建一個矩形使用上面的高度,和寬度
Rectangle rect = new Rectangle(width, height);
//元素坐標
Point p = element.getLocation();
裁剪全屏截圖
最后根據元素位置對整個圖片進行裁剪,創建一個element快照
如果元素過大,超過全屏截圖的范圍,這一步會報錯(y + height) is outside or not
,x+width同樣也會報錯
try{
BufferedImage img = image.getSubimage(p.getX(), p.getY(), rect.width, rect.height);
ImageIO.write(img, "png", screen);
}catch (Exception e){
e.printStackTrace();
}
元素過大的解決方案
- 創建全屏截圖時,根據滾動條創建長截圖
- 創建多個截圖,拼接成長截圖
- 退而求其次,只截圖全屏可見區域
方法1和方法2暫時不作解釋
這里對方法3描述一下
- 首先對元素的寬高,point的坐標簡單化
int w = rect.width; //指定矩形區域的寬度
int h = rect.height;//指定矩形區域的高度
int x = p.getX(); //指定矩形區域左上角的X坐標
int y = p.getY(); //指定矩形區域左上角的Y坐標
- 初始化瀏覽器的分辨率
//driver的分辨率,這里設置1920*1080
int w_driver = 1920;
int h_driver = 1080;
- 如果元素的寬加上坐標X或者元素的高加上坐標Y超過瀏覽器的分辨率,對元素的大小進行調整
if ( y + h > h_driver){ //(y + height) is outside or not
h = h- (y + h - h_driver);
}
if (x + w > w_driver){
w = x - (x + w - w_driver); //(x + width) is outside or not
}
- 開始裁剪
try{
BufferedImage img = image.getSubimage(x, y, w, h);
ImageIO.write(img, "png", screen);
}catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
完整代碼
package common;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.Point;
import org.openqa.selenium.chrome.ChromeDriver;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ElementSnapshot {
public static WebDriver driver;
/**
* main()方法調用
*
*/
public static void main(String[] args) throws Exception {
driver = new ChromeDriver();
driver.get("https://www.baidu.com");
driver.manage().window().maximize();
WebElement element = driver.findElement(By.id("su"));
String fileName = "filename";
//創建元素快照
elementSnapshot(driver,element);
//移動圖片到指定位置
FileUtils.copyFile(elementSnapshot(driver,element), new File(fileName, System.currentTimeMillis()+".png"));
}
/**
* 根據Element截圖指定區域方法
*
* @param driver
* @param element 截圖區域
* @throws Exception
*/
public static File elementSnapshot(WebDriver driver, WebElement element) throws Exception {
//創建全屏截圖
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
BufferedImage image = ImageIO.read(screen);
//獲取元素的高度、寬度
int width = element.getSize().getWidth();
int height = element.getSize().getHeight();
//創建一個矩形使用上面的高度,和寬度
Rectangle rect = new Rectangle(width, height);
//元素坐標
Point p = element.getLocation();
//對前面的矩形進行操作
//TODO 使用可以截全圖的方法(滾動條),暫未找到方式
int w = rect.width; //指定矩形區域的寬度
int h = rect.height;//指定矩形區域的高度
int x = p.getX(); //指定矩形區域左上角的X坐標
int y = p.getY(); //指定矩形區域左上角的Y坐標
//driver的分辨率,這里設置1920*1080
int w_driver = 1920;
int h_driver = 1080;
System.out.println("width:" + w);
System.out.println("height:"+ h);
System.out.println("x:"+ x);
System.out.println("y:"+ y);
System.out.println("y+height:"+(y + h));
System.out.println("x+width:"+ (x + w));
/**
* 如果Element的Y坐標值加上高度超過driver的高度
* 就會報錯(y + height) is outside or not
* 退而求其次,調整圖片的寬度和高度, 調整到適合driver的分辨率
* 此時會截圖driver可見的元素區域快照
* TODO 如果能找到跨滾動條截圖的方式,可以不用裁剪
*/
try{
if ( y + h > h_driver){
h = h- (y + h - h_driver); //
System.out.println("修改后的height:" + h);
System.out.println("修改后的y+height:"+ (y+h));
}
//(x + width) is outside or not
if (x + w > w_driver){
w = x - (x + w - w_driver);
System.out.println("修改后的width:"+ w);
System.out.println("修改后的x+width:"+ (x+w));
}
BufferedImage img = image.getSubimage(x, y, w, h);
ImageIO.write(img, "png", screen);
System.out.println("Screenshot By element success");
}catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
return screen;
}
}