17

当我使用 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 分辨率为 1920x1099,仅包含浏览器视口。
FirefoxDriver 的 test.png 分辨率为 1903x16559,包含整个页面。

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

我的问题是:

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

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

4

4 回答 4

11

我们无法使用 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<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;
    }
于 2013-12-12T08:01:31.933 回答
9

我清理了@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;
}
于 2015-07-14T01:28:01.533 回答
4

由于之前的实现存在一些不准确之处,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 中实现。但是,一旦您尝试了 .the Net 方法,我认为您不会回头=]

于 2013-06-03T04:00:07.833 回答
2

我偶然发现了同样的问题,ChromeDriver2 只是不支持它。

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

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

于 2013-08-16T12:51:56.530 回答