Selenium WebDriver C# 使用 ChromeDriver 和 FirefoxDriver 的完整网站截图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16795458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Selenium WebDriver C# Full Website Screenshots With ChromeDriver and FirefoxDriver
提问by user2429052
When I take screenshots with ChromeDriver I get screens with the size of my viewport.
When I take screenshots with FirefoxDriver I get what I want, which is a full screen print of a website.
当我使用 ChromeDriver 截取屏幕截图时,我会得到与我的视口大小相同的屏幕。
当我使用 FirefoxDriver 截取屏幕截图时,我得到了我想要的内容,即网站的全屏打印。
ChromeDriver is declared like this:
ChromeDriver 声明如下:
IWebDriver driver = new ChromeDriver();
FirefoxDriver is declared like this:
FirefoxDriver 声明如下:
IWebDriver driver = new FirefoxDriver();
Both drivers execute identical code:
两个驱动程序都执行相同的代码:
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's test.png is of 1920x1099 resolution and contains only the browser viewport.
FirefoxDriver's test.png is of 1903x16559 resolution and contains the whole page.
ChromeDriver 的 test.png 分辨率为 1920x1099,仅包含浏览器视口。
FirefoxDriver 的 test.png 分辨率为 1903x16559,包含整个页面。
I know that GetScreenshot()method doesn't return identical resolution sizes because it has slightly different implementations in IEDriver, FirefoxDriver, OperaDriver, ChromeDriver.
我知道该GetScreenshot()方法不会返回相同的分辨率大小,因为它在 IEDriver、FirefoxDriver、OperaDriver、ChromeDriver 中的实现略有不同。
My questions are:
我的问题是:
Why is there such difference between ChromeDriver's and FirefoxDriver's
.GetScreenshot()method, even tho they use an identical interface (ITakesScreenshot)?Is there a way to make ChromeDriver's
GetScreenshot()method return the whole webpage screen instead of just the viewport?
为什么 ChromeDriver 和 FirefoxDriver 的
.GetScreenshot()方法之间存在如此大的差异,即使它们使用相同的界面 (ITakesScreenshot)?有没有办法让 ChromeDriver 的
GetScreenshot()方法返回整个网页屏幕而不仅仅是视口?
回答by DeveloperInDevelopment
It appears as though full-screen screenshots are not yet implemented in the ChromeDriver, due to some inaccuracies in its previous implementation.
由于之前的实现中存在一些不准确之处,ChromeDriver 中似乎尚未实现全屏屏幕截图。
Source: https://code.google.com/p/chromedriver/issues/detail?id=294
来源:https: //code.google.com/p/chromedriver/issues/detail?id=294
I have recently written a Selenium based application to test an Internet Explorer UI and found that:
我最近编写了一个基于 Selenium 的应用程序来测试 Internet Explorer UI,发现:
- Taking screenshots with selenium was not as quick as using .NET, and
- Selenium is unable to take screenshots when dialog boxes are present. This was a major drawback, as I needed to identify unexpected dialogs during interaction with the pages.
- 使用 selenium 截取屏幕截图不如使用 .NET 快,而且
- 当出现对话框时,Selenium 无法截取屏幕截图。这是一个主要缺点,因为我需要在与页面交互期间识别意外的对话框。
Investigate using the Graphics.CopyFromScreen method in System.Drawing as an alternative solution until the feature is implemented in Chrome. Once you have tried .the Net approach however, I don't think you will look back =]
使用 System.Drawing 中的 Graphics.CopyFromScreen 方法作为替代解决方案进行调查,直到该功能在 Chrome 中实现。但是,一旦您尝试过 .the Net 方法,我认为您不会回头看 =]
回答by Roemer
I stumbled accross the same problem and ChromeDriver2 just does not support it.
我偶然发现了同样的问题,ChromeDriver2 只是不支持它。
So I created a little script which scrolls thru the page, takes screenshots and stitches everything together.
所以我创建了一个滚动页面的小脚本,截取屏幕截图并将所有内容拼接在一起。
You can find the script in my blog post here: http://dev.flauschig.ch/wordpress/?p=341
您可以在我的博客文章中找到该脚本:http: //dev.flauschig.ch/wordpress/?p=341
回答by S.Roshanth
we can't get the entire page screenshot with ChromeDriver2, we need to go for manual implementation.I have modified a method with is available in a blog which works fine with ChromeDriver.
我们无法使用 ChromeDriver2 获取整个页面的屏幕截图,我们需要手动实现。我修改了一个博客中提供的方法,该方法适用于 ChromeDriver。
use this method as following :
使用此方法如下:
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<Rectangle> rectangles = new List<Rectangle>();
// 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;
}
回答by Lachlan Goodhew-Cook
I cleaned up @Selvantharajah Roshanth's answer and added a check so that it won't try to stitch together screenshots that already fit in the viewport.
我清理了@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<Rectangle>();
// 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;
}

