Selenium: java.awt.image.RasterFormatException: (y + высота) находится за пределами растра при использовании размера и расположения элемента. - PullRequest
1 голос
/ 05 июля 2019

У меня есть код, который я взял из этого учебника. Он переходит на веб-сайт learn-selenium-easy.blogspot.com, ищет раздел «Самые популярные / популярные сообщения» и фотографирует его:

 class SshotofElement {

    public static void screenShotElement() throws InterruptedException,IOException {
        System.setProperty("webdriver.chrome.driver", "chromedriver.exe");

        DesiredCapabilities capabilities = DesiredCapabilities.chrome();
        capabilities.setCapability("marionette", true);
        WebDriver driver = new ChromeDriver(capabilities);

        driver.get("http://learn-selenium-easy.blogspot.com/");
        driver.manage().window().maximize();

        // Xpath of element to take screen shot
        WebElement element=driver.findElement(By.xpath("//*[@id='PopularPosts1']"));
        System.out.println(element.getSize());
        File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        // Take full screen screenshot
        BufferedImage  fullImg = ImageIO.read(screenshot);
        Point point = element.getLocation();
        int elementWidth = element.getSize().getWidth();
        int elementHeight = element.getSize().getHeight();
        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("mostread_screenshot.png"));//path to save screen shot

        driver.close();
    }
}

Я получаю исключение java.awt.image.RasterFormatException: (y + height) is outside of Raster, однако в строке BufferedImage elementScreenshot= fullImg.getSubimage(point.getX(), point.getY(), elementWidth,elementHeight);. Я не уверен, почему это так, поскольку точки и размер изображения взяты из самого элемента.

Ответы [ 2 ]

1 голос
/ 23 июля 2019

RasterFormatException

Согласно Java Docs RasterFormatException выбрасывается, если в Raster .

есть неверная информация о макете.

getLocation ()

Согласно документации Selenium getLocation() возвращает точку, содержащую местоположение верхнего левого угла элемента.


getSubimage ()

Согласно 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, т.е. elementScreenshot , который будет подизображением, определяемым указанной прямоугольной областью:

  • x: координата X левого верхнего угла указанной прямоугольной области - point.getX() - 104
  • y: координата Y левого верхнего угла указанной прямоугольной области - point.getY() - 744
  • w: ширина указанной прямоугольной области - elementWidth - 340
  • h: высота указанной прямоугольной области - elementHeight - 486

Итак, ожидаемая высота BufferedImage оказывается 744 + 486 = 1230, что в значительной степени превышает растр . Отсюда вы видите ошибку.


Решение

Чтобы сделать снимок экрана определенного элемента или определенного div с помощью и , вы можете использовать метод AShot(), импортирующий ashot -1.4.4.jar при работе с Selenium Java Client v3.14.0 , ChromeDriver v2.41 , Chrome v 68.0 .

Примечание : AShot() метод из ashot-1.4.4.jar работает только с jQuery включено веб-приложения .

  • Кодовый блок:

    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();
        }    
    }
    

Ссылки

Вы можете найти пару соответствующих обсуждений в:


Outro

Подробное обсуждение всех методов создания скриншотов, основанных на Java , можно найти в Как сделать скриншот с помощью Selenium WebDriver

1 голос
/ 22 июля 2019
  1. Изображение элемента, которое вы обрезаете, отсутствует на скриншоте, сделанном кодом. Если вы установите режим отладки и распечатаете путь для полноэкранного снимка и увидите его вручную, вы увидите, что требуемый элемент, который будет обрезан по изображению, отсутствует в нем.

  2. Итак, сначала нам нужно прокрутить страницу , чтобы привести нужный элемент в представление , а затем сделать снимок экрана. Затем нам нужно обрезать изображение в зависимости от местоположения элемента.

  3. Кроме того, класс Point не очень надежен для точного определения местоположения элемента.

  4. Во-вторых, если мы увидим значения ниже

    ImageIO.read(screenshot).getHeight() // ~ 943 => Total height
    element.getSize().getHeight() // ~ 511 => Element height 
    point.getY() // ~ 743 => start top side y coordinate of element
    
  5. Так что я считаю, что когда прямоугольник нарисован из 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

}

Окончательный субизображение здесь элемента после выполнения программы enter image description here

...