Selenium WebDriver С# Полный скриншоты сайта с 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 имеет разрешение 1920x1099 и содержит только окно просмотра браузера.
FirefoxDriver test.png имеет разрешение 1903x16559 и содержит всю страницу.

Я знаю, что метод GetScreenshot() не возвращает одинаковые разрешения, потому что он имеет несколько разные реализации в IEDriver, FirefoxDriver, OperaDriver, ChromeDriver.

Мои вопросы:

  • Почему существует такая разница между методом ChromeDriver и FirefoxDriver .GetScreenshot(), даже если они используют идентичный интерфейс (ITakesScreenshot)?

  • Есть ли способ заставить метод ChromeDriver GetScreenshot() вернуть весь экран веб-страницы вместо окна просмотра?

Ответы

Ответ 1

мы не можем получить весь скриншот страницы с 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;
    }

Ответ 2

Я очистил @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;
}

Ответ 3

Похоже, что полноэкранные скриншоты еще не реализованы в ChromeDriver из-за некоторых неточностей в его предыдущей реализации.

Источник: https://code.google.com/p/chromedriver/issues/detail?id=294

Недавно я написал приложение на основе Selenium для тестирования интерфейса Internet Explorer и обнаружил, что:

  • Снимки с селеном были не такими быстрыми, как использование .NET, и
  • Selenium не может делать скриншоты при наличии диалоговых окон. Это был главный недостаток, так как мне нужно было выявить неожиданные диалоги во время взаимодействия со страницами.

Изучите использование метода Graphics.CopyFromScreen в System.Drawing в качестве альтернативного решения, пока функция не будет реализована в Chrome. Однако, если вы попытались использовать метод Net, я не думаю, что вы оглянетесь назад =]

Ответ 4

Я столкнулся с той же проблемой, и ChromeDriver2 просто не поддерживает ее.

Итак, я создал немного script, который прокручивается через страницу, снимает скриншоты и строчки все вместе.

Вы можете найти script в моем блоге: http://dev.flauschig.ch/wordpress/?p=341