簡體   English   中英

Selenium WebDriver C#完整網站截圖使用ChromeDriver和FirefoxDriver

[英]Selenium WebDriver C# Full Website Screenshots With ChromeDriver and 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分辨率為1920x1099,僅包含瀏覽器視口。
FirefoxDriver的test.png分辨率為1903x16559,包含整個頁面。

我知道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<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;
    }

我清理了@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;
}

由於之前的實施中存在一些不准確之處,似乎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中實現該功能。 一旦你嘗試了網絡方法,我認為你不會回頭看=]

我遇到了同樣的問題,ChromeDriver2不支持它。

所以我創建了一個小腳本,通過頁面滾動,截取屏幕截圖並將所有內容拼接在一起。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM