Wie kann man mit seleniumium Webdriver den Screenshot eines bestimmten Elements statt der gesamten Seite erfassen?

Momentan versuche ich einen Screenshot mit dem seleniumium WebDriver zu erstellen. Aber ich kann nur die ganze Seite Screenshot erhalten. Was ich jedoch wollte, ist nur einen Teil der Seite oder vielleicht nur ein bestimmtes Element basierend auf der ID oder einem bestimmten Element-Locator zu erfassen. (Zum Beispiel möchte ich das Bild mit image id = “Butterfly” aufnehmen)

Gibt es eine Möglichkeit, einen Screenshot nach ausgewähltem Element oder Element aufzunehmen?

Wir können den Element-Screenshot erhalten, indem wir den gesamten Seiten-Screenshot wie folgt zuschneiden:

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

In Node.js ich den folgenden Code geschrieben, der funktioniert, aber er basiert nicht auf dem offiziellen WebDriverJS von selenium, sondern auf SauceLabs's WebDriver SauceLabs : WD.js und einer sehr kompakten Bildbibliothek namens EasyImage .

Ich möchte nur betonen, dass du den Screenshot eines Elements nicht wirklich machen kannst, aber was du tun solltest, ist zunächst, den Screenshot der ganzen Seite zu machen, dann den Teil der Seite auszuwählen, den du magst, und diesen bestimmten Teil zuzuschneiden:

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

Und die cropInFileFunction, geht so:

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

Das ASHOT-Framework von Yandex kann für Screenshots in seleniumium WebDriver-Skripten verwendet werden

  • volle Webseiten
  • Webelemente

Dieses Framework finden Sie unter https://github.com/yandex-qatools/ashot .

Der Code für die Screenshots ist sehr einfach:

Ganze Seite

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

SPEZIFISCHES WEB ELEMENT

 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")); 

Weitere Details und weitere Codebeispiele finden Sie in diesem Artikel .

Ich habe viel Zeit damit verschwendet, Screenshots zu machen, und ich möchte deine retten. Ich habe Chrom + selenium + C # verwendet, das Ergebnis war total schrecklich. Endlich habe ich eine function geschrieben:

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

Für alle, die nach Code in C # fragen, finden Sie unten eine vereinfachte Version meiner Implementierung.

 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:\seleniumiumScreenshots\" + fileName, System.Drawing.Imaging.ImageFormat.Jpeg)); } catch (Exception e) { logger.Error(e.StackTrace + ' ' + e.Message); } } 

Suryas Antwort funktioniert gut, wenn es Ihnen nichts ausmacht, mit Disk IO zu arbeiten. Wenn Sie nicht möchten, dann ist diese Methode möglicherweise besser für Sie

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

Wenn Sie bevorzugen, können Sie deklarieren screengrab und stattdessen tun

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

Das ist sauberer, aber ich habe es für Klarheit gelassen. Sie können es dann als Datei speichern oder nach Herzenslust in eine JPanel einfügen .

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

Betrachten Sie die Verwendung von nadel – tool für den automatisierten visuellen Vergleich https://github.com/bfirsh/needle , das über eine integrierte functionalität verfügt, mit der Screenshots von bestimmten Elementen (ausgewählt mit dem CSS – Selektor) erstellt werden können. Das Tool arbeitet an seleniumiums WebDriver und ist in Python geschrieben.

Unterhalb der function zum Erstellen eines Schnappschusses für ein bestimmtes Element in seleniumium. Hier ist der Treiber eine Art 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); } 

Wenn Sie nach einer JavaScript-Lösung suchen, hier ist mein core:

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

Die Grundidee ist die gleiche, nehmen Sie zuerst den Screenshot, dann schneiden Sie ihn ab. Meine Lösung erfordert jedoch keine anderen Bibliotheken, sondern nur reinen WebDriver-API-Code. Der Nebeneffekt ist jedoch, dass es die Belastung Ihres Testbrowsers erhöhen kann.

Hier ist eine Erweiterungsfunktion für 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(); } } 

Jetzt können Sie es verwenden, um das Bild eines Elements wie folgt aufzunehmen:

 var image = webDriver.GetElementImage(By.Id("someId")); 

Hier ist eine Python 3-Version mit seleniumium-Webdriver und Pillow. Dieses Programm erfasst den Screenshot der gesamten Seite und beschneidet das Element basierend auf seinem Standort. Das Elementbild wird als image.png verfügbar sein

 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') 
 using System.Drawing; using System.Drawing.Imaging; using OpenQA.seleniumium; using OpenQA.seleniumium.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); } } } } 

Ich glaube, das wird nicht für Sie funktionieren, wenn Sie C # verwenden und meine Lösung enthält eine Java-Bibliothek, aber vielleicht finden es andere hilfreich.

Zum Aufnehmen von benutzerdefinierten Screenshots können Sie die Shutterbug-Bibliothek verwenden. Der spezifische Aufruf für diesen Zweck wäre:

 Shutterbug.shootElement(driver, element).save(); 

Ich benutze eine modifizierte Version von @ Brooks Antwort und funktioniert auch für Elemente, die die zu scrollende Seite benötigt.

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

Die beiden if notwendig waren (zumindest für den Chrome-Treiber), weil die Größe des Crop in 1 Pixel die Screenshotgröße überschritt, als Scrolling benötigt wurde.