Selenium WebDriver C#完整网站截图使用ChromeDriver和FirefoxDriver

当我使用ChromeDriver截取屏幕截图时,我会获得具有视口大小的屏幕。
当我使用FirefoxDriver截取屏幕截图时,我得到了我想要的内容,这是一个网站的全屏幕打印。

ChromeDriver声明如下:

IWebDriver driver = new ChromeDriver(); 

FirefoxDriver声明如下:

 IWebDriver driver = new FirefoxDriver(); 

两个驱动程序执行相同的代

 driver.Manage().Window.Maximize(); driver.Navigate().GoToUrl(url);//url is a string variable ITakesScreenshot screenshotDriver = driver as ITakesScreenshot; Screenshot screenshot = screenshotDriver.GetScreenshot(); screenshot.SaveAsFile("c:/test.png", ImageFormat.Png); 

ChromeDriver的test.png分辨率为1920×1099,仅包含浏览器视口。
FirefoxDriver的test.png分辨率为1903×16559,包含整个页面。

我知道GetScreenshot()方法不会返回相同的分辨率大小,因为它在IEDriver,FirefoxDriver,OperaDriver,ChromeDriver中的实现略有不同。

我的问题是:

  1. 为什么ChromeDriver和FirefoxDriver的.GetScreenshot()方法之间存在这样的差异,即使他们使用相同的界面(ITakesScreenshot)?

  2. 有没有办法让ChromeDriver的GetScreenshot()方法返回整个网页屏幕而不仅仅是视口?

我们无法使用ChromeDriver2获取整个页面截图,我们需要手动实现。我已经修改了一个方法,可以在博客中使用ChromeDriver工作正常。

使用此方法如下:

 private IWebDriver _driver = new ChromeDriver(CHROME_DRIVER_PATH); screenshot.SaveAsFile(saveFileName, ImageFormat.Jpeg); public Bitmap GetEntereScreenshot() { Bitmap stitchedImage = null; try { long totalwidth1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.offsetWidth");//documentElement.scrollWidth"); long totalHeight1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.parentNode.scrollHeight"); int totalWidth = (int)totalwidth1; int totalHeight = (int)totalHeight1; // Get the Size of the Viewport long viewportWidth1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.clientWidth");//documentElement.scrollWidth"); long viewportHeight1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return window.innerHeight");//documentElement.scrollWidth"); int viewportWidth = (int)viewportWidth1; int viewportHeight = (int)viewportHeight1; // Split the Screen in multiple Rectangles List rectangles = new List(); // Loop until the Total Height is reached for (int i = 0; i < totalHeight; i += viewportHeight) { int newHeight = viewportHeight; // Fix if the Height of the Element is too big if (i + viewportHeight > totalHeight) { newHeight = totalHeight - i; } // Loop until the Total Width is reached for (int ii = 0; ii < totalWidth; ii += viewportWidth) { int newWidth = viewportWidth; // Fix if the Width of the Element is too big if (ii + viewportWidth > totalWidth) { newWidth = totalWidth - ii; } // Create and add the Rectangle Rectangle currRect = new Rectangle(ii, i, newWidth, newHeight); rectangles.Add(currRect); } } // Build the Image stitchedImage = new Bitmap(totalWidth, totalHeight); // Get all Screenshots and stitch them together Rectangle previous = Rectangle.Empty; foreach (var rectangle in rectangles) { // Calculate the Scrolling (if needed) if (previous != Rectangle.Empty) { int xDiff = rectangle.Right - previous.Right; int yDiff = rectangle.Bottom - previous.Bottom; // Scroll //selenium.RunScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff)); ((IJavaScriptExecutor)_driver).ExecuteScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff)); System.Threading.Thread.Sleep(200); } // Take Screenshot var screenshot = ((ITakesScreenshot)_driver).GetScreenshot(); // Build an Image out of the Screenshot Image screenshotImage; using (MemoryStream memStream = new MemoryStream(screenshot.AsByteArray)) { screenshotImage = Image.FromStream(memStream); } // Calculate the Source Rectangle Rectangle sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height); // Copy the Image using (Graphics g = Graphics.FromImage(stitchedImage)) { g.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel); } // Set the Previous Rectangle previous = rectangle; } } catch (Exception ex) { // handle } return stitchedImage; } 

我清理了@Selvantharajah Roshanth的答案,并添加了一个检查,以便它不会尝试将已经适合视口的屏幕截图拼接在一起。

 public Image GetEntireScreenshot() { // Get the total size of the page var totalWidth = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return document.body.offsetWidth"); //documentElement.scrollWidth"); var totalHeight = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return document.body.parentNode.scrollHeight"); // Get the size of the viewport var viewportWidth = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return document.body.clientWidth"); //documentElement.scrollWidth"); var viewportHeight = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return window.innerHeight"); //documentElement.scrollWidth"); // We only care about taking multiple images together if it doesn't already fit if (totalWidth <= viewportWidth && totalHeight <= viewportHeight) { var screenshot = driver.TakeScreenshot(); return ScreenshotToImage(screenshot); } // Split the screen in multiple Rectangles var rectangles = new List(); // Loop until the totalHeight is reached for (var y = 0; y < totalHeight; y += viewportHeight) { var newHeight = viewportHeight; // Fix if the height of the element is too big if (y + viewportHeight > totalHeight) { newHeight = totalHeight - y; } // Loop until the totalWidth is reached for (var x = 0; x < totalWidth; x += viewportWidth) { var newWidth = viewportWidth; // Fix if the Width of the Element is too big if (x + viewportWidth > totalWidth) { newWidth = totalWidth - x; } // Create and add the Rectangle var currRect = new Rectangle(x, y, newWidth, newHeight); rectangles.Add(currRect); } } // Build the Image var stitchedImage = new Bitmap(totalWidth, totalHeight); // Get all Screenshots and stitch them together var previous = Rectangle.Empty; foreach (var rectangle in rectangles) { // Calculate the scrolling (if needed) if (previous != Rectangle.Empty) { var xDiff = rectangle.Right - previous.Right; var yDiff = rectangle.Bottom - previous.Bottom; // Scroll ((IJavaScriptExecutor) driver).ExecuteScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff)); } // Take Screenshot var screenshot = driver.TakeScreenshot(); // Build an Image out of the Screenshot var screenshotImage = ScreenshotToImage(screenshot); // Calculate the source Rectangle var sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height); // Copy the Image using (var graphics = Graphics.FromImage(stitchedImage)) { graphics.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel); } // Set the Previous Rectangle previous = rectangle; } return stitchedImage; } private static Image ScreenshotToImage(Screenshot screenshot) { Image screenshotImage; using (var memStream = new MemoryStream(screenshot.AsByteArray)) { screenshotImage = Image.FromStream(memStream); } return screenshotImage; } 

由于之前的实施中存在一些不准确之处,似乎ChromeDriver中尚未实现全屏截图。

资料来源: https : //code.google.com/p/chromedriver/issues/detail?id = 294

我最近写了一个基于Selenium的应用程序来测试Internet Explorer UI,发现:

  1. 用selenium截取屏幕并不像使用.NET那样快
  2. 当存在对话框时,Selenium无法截取屏幕截图。 这是一个主要缺点,因为我需要在与页面交互期间识别意外的对话框。

在使用System.Drawing中的Graphics.CopyFromScreen方法作为替代解决方案进行调查,直到在Chrome中实现该function。 一旦你尝试过网络方法,我认为你不会回头看看=]

我遇到了同样的问题,ChromeDriver2不支持它。

所以我创建了一个小脚本,它通过页面滚动,截取屏幕截图并将所有内容拼接在一起。

您可以在我的博客文章中找到该脚本: http : //dev.flauschig.ch/wordpress/?p = 341