web-dev-qa-db-fra.com

Comment capturer la capture d'écran d'un élément spécifique plutôt que de la page entière avec Selenium Webdriver?

Actuellement, j'essaie de capturer une capture d'écran à l'aide du Selenium WebDriver. Mais je ne peux obtenir que la capture d'écran de la page entière. Cependant, ce que je voulais, c’était juste de capturer une partie de la page ou peut-être juste un élément spécifique basé sur un identifiant ou un localisateur d’élément spécifique. (Par exemple, je souhaite capturer l'image avec image id = "Butterfly")

Est-il possible de capturer une capture d'écran avec l'élément ou l'élément sélectionné?

60
fj123

Nous pouvons obtenir la capture d'écran de l'élément en découpant la capture de la page entière comme ci-dessous:

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);
92
Surya

Dans Node.js, j’ai écrit le code suivant qui fonctionne, mais il n’est pas basé sur WebDriverJS officiel de Selenium, mais sur SauceLabs's WebDriver: WD.js et une bibliothèque d’images très compacte appelée EasyImage

Je veux juste souligner que vous ne pouvez pas vraiment prendre la capture d'écran d'un élément, mais ce que vous devez faire est tout d'abord de prendre la capture d'écran de la page entière, puis de sélectionner la partie de la page que vous aimez et de recadrer cette partie spécifique:

browser.get(URL_TO_VISIT)
       .waitForElementById(dependentElementId, webdriver.asserters.isDisplayed, 3000)
       .elementById(elementID)
        .getSize().then(function(size) {
            browser.elementById(elementID)
                   .getLocation().then(function(location) {
                        browser.takeScreenshot().then(function(data) {
                            var base64Data = data.replace(/^data:image\/png;base64,/, "");
                            fs.writeFile(filePath, base64Data, 'base64', function(err) {
                                if (err) {
                                    console.log(err);
                                } 
                                else {
                                    cropInFile(size, location, filePath);
                                }
                                doneCallback();
                        });
                    });
                });
            }); 

Et le cropInFileFunction, va comme ceci:

var cropInFile = function(size, location, srcFile) {
    easyimg.crop({
            src: srcFile,
            dst: srcFile,
            cropwidth: size.width,
            cropheight: size.height,
            x: location.x,
            y: location.y,
            gravity: 'North-West'
        },
        function(err, stdout, stderr) {
            if (err) throw err;
        });
};
10
ambodi

Le framework ASHOT de Yandex peut être utilisé pour prendre des captures d’écran dans les scripts Selenium WebDriver pour

  • pages web complètes
  • éléments web

Ce cadre est disponible sur https://github.com/yandex-qatools/ashot .

Le code pour prendre les captures d'écran est très simple:

PAGE ENTIÈRE

screenshot = new AShot().shootingStrategy(
new ViewportPastingStrategy(1000)).takeScreenshot(driver);
ImageIO.write(screenshot.getImage(), "PNG", new File("c:\\temp\\results.png"));

ÉLÉMENT WEB SPÉCIFIQUE

screenshot = new AShot().takeScreenshot(driver, 
driver.findElement(By.xpath("(//div[@id='ct_search'])[1]")));

ImageIO.write(screenshot.getImage(), "PNG", new File("c:\\temp\\div_element.png"));

Voir plus de détails et d’échantillons de code sur cet article .

8
Alex Siminiuc

Pour tous ceux qui demandent du code en C #, voici une version simplifiée de mon implémentation.

public static void TakeScreenshot(IWebDriver driver, IWebElement element)
{
    try
    {
        string fileName = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".jpg";
        Byte[] byteArray = ((ITakesScreenshot)driver).GetScreenshot().AsByteArray;
        System.Drawing.Bitmap screenshot = new System.Drawing.Bitmap(new System.IO.MemoryStream(byteArray));
        System.Drawing.Rectangle croppedImage = new System.Drawing.Rectangle(element.Location.X, element.Location.Y, element.Size.Width, element.Size.Height);
        screenshot = screenshot.Clone(croppedImage, screenshot.PixelFormat);
        screenshot.Save(String.Format(@"C:\SeleniumScreenshots\" + fileName, System.Drawing.Imaging.ImageFormat.Jpeg));
    }
    catch (Exception e)
    {
        logger.Error(e.StackTrace + ' ' + e.Message);
    }
}
4
Brook

J'ai perdu beaucoup de temps à prendre une capture d'écran et je veux sauvegarder la vôtre. J'ai utilisé chrome + sélénium + c # le résultat était totalement horrible. Enfin j'ai écrit une fonction:

driver.Manage().Window.Maximize();
             RemoteWebElement remElement = (RemoteWebElement)driver.FindElement(By.Id("submit-button")); 
             Point location = remElement.LocationOnScreenOnceScrolledIntoView;  

             int viewportWidth = Convert.ToInt32(((IJavaScriptExecutor)driver).ExecuteScript("return document.documentElement.clientWidth"));
             int viewportHeight = Convert.ToInt32(((IJavaScriptExecutor)driver).ExecuteScript("return document.documentElement.clientHeight"));

             driver.SwitchTo();

             int elementLocation_X = location.X;
             int elementLocation_Y = location.Y;

             IWebElement img = driver.FindElement(By.Id("submit-button"));

             int elementSize_Width = img.Size.Width;
             int elementSize_Height = img.Size.Height;

             Size s = new Size();
             s.Width = driver.Manage().Window.Size.Width;
             s.Height = driver.Manage().Window.Size.Height;

             Bitmap bitmap = new Bitmap(s.Width, s.Height);
             Graphics graphics = Graphics.FromImage(bitmap as Image);
             graphics.CopyFromScreen(0, 0, 0, 0, s);

             bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);

             RectangleF part = new RectangleF(elementLocation_X, elementLocation_Y + (s.Height - viewportHeight), elementSize_Width, elementSize_Height);

             Bitmap bmpobj = (Bitmap)Image.FromFile(filePath);
             Bitmap bn = bmpobj.Clone(part, bmpobj.PixelFormat);
             bn.Save(finalPictureFilePath, System.Drawing.Imaging.ImageFormat.Png); 
4
user2504655

Voici une version Python 3 utilisant Selenium Webdriver and Pillow . Ce programme capture la capture d'écran de la page entière et recadre l'élément en fonction de son emplacement. L'image de l'élément sera disponible en tant que image.png

from Selenium import webdriver
from PIL import Image

driver = webdriver.Chrome()
driver.get('https://www.google.co.in')

element = driver.find_element_by_id("lst-ib")

location = element.location
size = element.size

driver.save_screenshot("shot.png")

x = location['x']
y = location['y']
w = size['width']
h = size['height']
width = x + w
height = y + h

im = Image.open('shot.png')
im = im.crop((int(x), int(y), int(width), int(height)))
im.save('image.png')
3
Rohith R Nair

Voici une fonction d'extension pour C #:

public static BitmapImage GetElementImage(this IWebDriver webDriver, By by)
{
    var elements = webDriver.FindElements(by);
    if (elements.Count == 0)
        return null;

    var element = elements[0];
    var screenShot = (webDriver as ITakesScreenshot).GetScreenshot();
    using (var ms = new MemoryStream(screenShot.AsByteArray))
    {
        Bitmap screenBitmap;
        screenBitmap = new Bitmap(ms);
        return screenBitmap.Clone(
            new Rectangle(
                element.Location.X,
                element.Location.Y,
                element.Size.Width,
                element.Size.Height
            ),
            screenBitmap.PixelFormat
        ).ToBitmapImage();
    }
}

Maintenant, vous pouvez l'utiliser pour prendre l'image de n'importe quel élément comme celui-ci:

var image = webDriver.GetElementImage(By.Id("someId"));
2
Hüseyin Yağlı

La réponse de Surya fonctionne très bien si l'implication du disque IO vous dérange pas. Si vous préférez ne pas le faire, cette méthode peut être meilleure pour vous.

private Image getScreenshot(final WebDriver d, final WebElement e) throws IOException {
    final BufferedImage img;
    final Point topleft;
    final Point bottomright;

    final byte[] screengrab;
    screengrab = ((TakesScreenshot) d).getScreenshotAs(OutputType.BYTES);

    img = ImageIO.read(new ByteArrayInputStream(screengrab));

    //crop the image to focus on e
    //get dimensions (crop points)
    topleft = e.getLocation();
    bottomright = new Point(e.getSize().getWidth(),
                            e.getSize().getHeight());

    return img.getSubimage(topleft.getX(),
                           topleft.getY(),
                           bottomright.getX(),
                           bottomright.getY());
}

Si vous préférez, vous pouvez ignorer déclarer screengrab et faire plutôt 

img = ImageIO.read(
    new ByteArrayInputStream(
        ((TakesScreenshot) d).getScreenshotAs(OutputType.BYTES)));

ce qui est plus propre, mais je l’ai laissé pour plus de clarté. Vous pouvez ensuite l'enregistrer sous forme de fichier ou le placer dans un fichier JPanel comme bon vous semble.

2
rath
public void GenerateSnapshot(string url, string selector, string filePath)
    {
        using (IWebDriver driver = new ChromeDriver())
        {
            driver.Navigate().GoToUrl(url);
            var remElement = driver.FindElement(By.CssSelector(selector));
            Point location = remElement.Location;

            var screenshot = (driver as ChromeDriver).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, System.Drawing.Imaging.ImageFormat.Png);
                    }
                }
            }
            driver.Close();
        }
    }
2
Waqar Ullah Khan

Si vous recherchez une solution JavaScript, voici mon résumé:

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

L'idée de base est la même: prenez d'abord la capture d'écran, puis recadrez-la . Cependant, ma solution ne nécessitera pas d'autres bibliothèques, mais uniquement du code pur API WebDriver. Cependant, l’effet secondaire est que cela peut augmenter la charge de votre navigateur de test.

1
sillicon

Au-dessous de la fonction permettant de prendre en instantané un élément spécifique dans Sélénium. Ici, le pilote est un type de 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);
 }
1
ER.swatantra

Pensez à utiliser needle - tool pour une comparaison visuelle automatisée https://github.com/bfirsh/needle , Qui possède une fonctionnalité intégrée qui permet de prendre des captures d’écran d’éléments spécifiques ). L'outil fonctionne sur le WebDriver de Selenium et est écrit en Python.

1
Jan Rozycki
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);                        
            }
        }
    }
}
0
Mnemo

Si vous obtenez une exception Java.awt.image.RasterFormatException in chrome, ou si vous souhaitez faire défiler un élément dans la vue, capturez une capture d'écran. 

Voici une solution de @Surya answer.

        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);
0
Green Lei

c # code:

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;
}
0
Andrew

Python 3

Essayé avec Selenium 3.141.0 et chromedriver 73.0.3683.68, cela fonctionne,

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')

Pas besoin d'obtenir une image complète et d'obtenir une section d'une image plein écran.

Cela n'était peut-être pas disponible lorsque la réponse de Rohit a été créée.

0
rovr138