如何使用Selenium Webdriver捕获特定元素而不是整个页面的屏幕截图?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Selenium Webdriver捕获特定元素而不是整个页面的屏幕截图?相关的知识,希望对你有一定的参考价值。

目前我正在尝试使用Selenium WebDriver捕获屏幕截图。但我只能获得整页屏幕截图。但是,我想要的只是捕获页面的一部分,或者只是基于ID或任何特定元素定位器捕获特定元素。 (例如,我希望用图像id =“Butterfly”捕获图片)

有没有办法按选定的项目或元素捕获屏幕截图?

答案

我们可以通过裁剪整个页面截图来获取元素截图,如下所示:

driver.get("http://www.google.com");
WebElement ele = driver.findElement(By.id("hplogo"));

// Get entire page screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage  fullImg = ImageIO.read(screenshot);

// Get the location of element on the page
Point point = ele.getLocation();

// Get width and height of the element
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();

// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(),
    eleWidth, eleHeight);
ImageIO.write(eleScreenshot, "png", screenshot);

// Copy the element screenshot to disk
File screenshotLocation = new File("C:\\images\\GoogleLogo_screenshot.png");
FileUtils.copyFile(screenshot, screenshotLocation);
另一答案

考虑使用针 - 工具进行自动视觉比较https://github.com/bfirsh/needle,它具有内置功能,可以截取特定元素的截图(由CSS选择器选择)。该工具适用于Selenium的WebDriver,它是用Python编写的。

另一答案

下面是在Selenium中拍摄特定元素的快照功能。这里的驱动程序是一种WebDriver。

private static void getScreenshot(final WebElement e, String fileName) throws IOException {
  final BufferedImage img;
  final Point topleft;
  final Point bottomright;
  final byte[] screengrab;
  screengrab = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
  img = ImageIO.read(new ByteArrayInputStream(screengrab));
  topleft = e.getLocation();
  bottomright = new Point(e.getSize().getWidth(), e.getSize().getHeight());
  BufferedImage imgScreenshot= 
      (BufferedImage)img.getSubimage(topleft.getX(), topleft.getY(), bottomright.getX(), bottomright.getY());
  File screenshotLocation = new File("Images/"+fileName +".png");    
  ImageIO.write(imgScreenshot, "png", screenshotLocation);
 }
另一答案

如果您正在寻找javascript解决方案,请参阅我的要点:

https://gist.github.com/sillicon/4abcd9079a7d29cbb53ebee547b55fba

基本思路是一样的,首先拍摄屏幕截图,然后裁剪。但是,我的解决方案不需要其他库,只需要纯WebDriver API代码。但是,副作用是它可能会增加测试浏览器的负载。

另一答案

Python 3

尝试使用Selenium 3.141.0和chromedriver 73.0.3683.68,这是有效的,

from selenium import webdriver

chromedriver = '/usr/local/bin/chromedriver'
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('window-size=1366x768')
chromeOptions.add_argument('disable-extensions')
cdriver = webdriver.Chrome(options=chromeOptions, executable_path=chromedriver)

cdriver.get('url')
element = cdriver.find_element_by_css_selector('.some-css.selector')

element.screenshot_as_png('elemenent.png')

无需获取完整图像并获取全屏图像的一部分。

Rohit's answer创建时,这可能不可用。

另一答案
using System.Drawing;
using System.Drawing.Imaging;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

public void ScreenshotByElement()
{
    IWebDriver driver = new FirefoxDriver();
    String baseURL = "www.google.com/"; //url link
    String filePath = @"c:\\img1.png";      

    driver.Navigate().GoToUrl(baseURL);
    var remElement = driver.FindElement(By.Id("Butterfly"));
    Point location = remElement.Location;

    var screenshot = (driver as FirefoxDriver).GetScreenshot();
    using (MemoryStream stream = new MemoryStream(screenshot.AsByteArray))
    {
        using (Bitmap bitmap = new Bitmap(stream))
        {
            RectangleF part = new RectangleF(location.X, location.Y, remElement.Size.Width, remElement.Size.Height);
            using (Bitmap bn = bitmap.Clone(part, bitmap.PixelFormat))
            {
                bn.Save(filePath, ImageFormat.Png);                        
            }
        }
    }
}
另一答案

如果在chrome中遇到异常java.awt.image.RasterFormatException,或者想要将元素滚动到视图中,则捕获屏幕截图。

这是来自@Surya答案的解决方案。

        JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
        Long offsetTop = (Long) jsExecutor.executeScript("window.scroll(0, document.querySelector(\""+cssSelector+"\").offsetTop - 0); return document.querySelector(\""+cssSelector+"\").getBoundingClientRect().top;");

        WebElement ele = driver.findElement(By.cssSelector(cssSelector));

        // Get entire page screenshot
        File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        BufferedImage  fullImg = ImageIO.read(screenshot);

        // Get the location of element on the page
        Point point = ele.getLocation();

        // Get width and height of the element
        int eleWidth = ele.getSize().getWidth();
        int eleHeight = ele.getSize().getHeight();

        // Crop the entire page screenshot to get only element screenshot
        BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), Math.toIntExact(offsetTop),
                eleWidth, eleHeight);
        ImageIO.write(eleScreenshot, "png", screenshot);

        // Copy the element screenshot to disk
        File screenshotLocation = new File("c:\\temp\\div_element_1.png");
        FileUtils.copyFile(screenshot, screenshotLocation);
另一答案

c#代码:

public Bitmap MakeElemScreenshot( IWebDriver driver, WebElement elem)
{
    Screenshot myScreenShot = ((ITakesScreenshot)driver).GetScreenshot();

    Bitmap screen = new Bitmap(new MemoryStream(myScreenShot.AsByteArray));
    Bitmap elemScreenshot = screen.Clone(new Rectangle(elem.Location, elem.Size), screen.PixelFormat);

    screen.Dispose();

    return elemScreenshot;
}
另一答案

我相信这对你不起作用,因为你使用C#并且我的解决方案包含一个Java库,但也许其他人会发现它有用。

要捕获自定义屏幕截图,您可以使用Shutterbug库。为此目的的具体要求是:

Shutterbug.shootElement(driver, element).save();
另一答案

我正在使用@ Brook的答案的修改版本,即使对于需要滚动页面的元素也能正常工作。

public void TakeScreenshot(string fileNameWithoutExtension, IWebElement element)
{
    // Scroll to the element if necessary
    var actions = new Actions(_driver);
    actions.MoveToElement(element);
    actions.Perform();
    // Get the element position (scroll-aware)
    var locationWhenScrolled = ((RemoteWebElement) element).LocationOnScreenOnceScrolledIntoView;
    var fileName = fileNameWithoutExtension + ".png";
    var byteArray = ((ITakesScreenshot) _driver).GetScreenshot().AsByteArray;
    using (var screenshot = new System.Drawing.Bitmap(new System.IO.MemoryStream(byteArray)))
    {
        var location = locationWhenScrolled;
        // Fix location if necessary to avoid OutOfMemory Exception
        if (location.X + element.Size.Width > screenshot.Width)
        {
            location.X = screenshot.Width - element.Size.Width;
        }
        if (location.Y + element.Size.Height > screenshot.Height)
        {
            location.Y = screenshot.Height - element.Size.Height;
        }
        // Crop the screenshot
        var croppedImage = new System.Drawing.Rectangle(location.X, location.Y, element.Size.Width, element.Size.Height);
        using (var clone = screenshot.Clone(croppedImage, screenshot.PixelFormat))
        {
            clone.Save(fileName, ImageFormat.Png);
        }
    }
}

两个ifs是必要的(至少对于chrome驱动程序),因为当需要滚动时,裁剪的大小超过屏幕截图大小的1个像素。

另一答案

Node.js中,我编写了以下代码,但它不是基于selenium的官方WebDriverJS,而是基于SauceLabs's WebDriver如何使用 Selenium Webdriver 捕获特定元素而不是整个页面的屏幕截图?我尝试了已经可用的答案

如何在不调整窗口大小的情况下使用 Java 在 Selenium Webdriver 中捕获屏幕截图 [重复]

使用 Java 使用 Selenium WebDriver 捕获浏览器日志

在 selenium webdriver 中捕获屏幕截图 [重复]

无法使用 selenium webdriver 3.0.0-beta3 捕获完整的网页截图

如何用selenium webdriver 捕获js error