Selenium webdriver C# - 全页截图

时间:2012-05-09 05:28:13

标签: webdriver screenshot selenium-webdriver

任何人都可以帮我使用Selenium webdriver拍摄整页截图。我正在使用c#/ Nunit。我正在使用的当前方法没有采用完整的浏览器页面。

我使用下面的代码截取屏幕截图。

public void TakeScreenShot(IWebDriver webDriver,string testName,string className)
{          

string folderName = String.Format("{0}.{1}", className, testName);

// Create Screenshot folder
string createdFolderLocation = CreateFolder(folderName);

// Take the screenshot            
Screenshot ss = ((ITakesScreenshot)webDriver).GetScreenshot();            
string screenshot = ss.AsBase64EncodedString;
byte[] screenshotAsByteArray = ss.AsByteArray;

// Save the screenshot
ss.SaveAsFile((string.Format("{0}\\{1}",createdFolderLocation,testName + ".Jpeg")), System.Drawing.Imaging.ImageFormat.Jpeg);
ss.ToString();

}

10 个答案:

答案 0 :(得分:3)

“整页”屏幕截图由WebDriver定义,包括浏览器中显示的整个页面,而不是浏览器镶边(URL栏,工具栏,窗口调整大小手柄等)。如果您不关心在屏幕截图中获取完整的DOM,则无需使用WebDriver来获取屏幕截图。您可以使用操作系统的API来处理它。

答案 1 :(得分:2)

您可以使用此软件包https://www.nuget.org/packages/Noksa.WebDriver.ScreenshotsExtensions/

为了获取整个页面的屏幕截图,请使用VerticalCombineDecorator:

var vcs = new VerticalCombineDecorator(new ScreenshotMaker());
var screen = _driver.TakeScreenshot(vcs);

答案 2 :(得分:1)

在拍摄屏幕截图之前,请尝试将浏览器窗口的大小更改为巨大的内容。我的尺寸比宽度小10,比高度小10。尝试添加而不是减去。

    driver = new FirefoxDriver(firefoxProfile);

    if (Config.MAXIMIZE_BROWSER_WINDOW)
    {
        driver.Manage().Window.Size = new System.Drawing.Size(System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width - 10, System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height - 10);
    }

答案 3 :(得分:1)

你可以试试这个

IWebDriver driver = new PhantomJSDriver();
driver.Navigate().GoToUrl("http://www.google.com");
((ITakesScreenshot)driver).GetScreenshot().SaveAsFile("image.png", ImageFormat.Png);

答案 4 :(得分:0)

我记得((ITakesScreenshot)webDriver).GetScreenshot();获取整页截图,但如果你有一些ajax请求和其他加载元素,你可以添加滚动,并在最后等待几秒钟,之后你会知道它需要完整加载的页面截图。

        for (int second = 0;; second++)
        {
            if (second >= 4)
            {
                break;
            }

            ((IJavaScriptExecutor)Global.Driver).ExecuteScript("window.scrollBy(0,800)", string.Empty);
            Thread.Sleep(500);
        }

        Thread.Sleep(3000);

答案 5 :(得分:0)

试试这个希望它能适合你。

public void TakeScreenshot(string SSName)
        {
            try
            {
                string path = "D:\\WorkSpace\\Screenshot\\";
                Screenshot ss = ((ITakesScreenshot)driver).GetScreenshot();
                ss.SaveAsFile((path + SSName), System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw;
            }
        }

答案 6 :(得分:0)

2017年的问候))!

如果页面尺寸大于屏幕尺寸 - 您可以使用PhantomJS驱动程序(PhantomJS download page

var fileName = "test.png";
var size = new Size(800, 2000);
var url = "https://stackoverflow.com/";

using (var driver = new PhantomJSDriver())
{
    driver.Manage().Window.Size = size;
    driver.Navigate().GoToUrl(url);
    ((ITakesScreenshot)driver)
        .GetScreenshot()
        .SaveAsFile(fileName, ImageFormat.Png);

    driver.Close();
}

答案 7 :(得分:0)

我在解决方案中使用的那个

 public byte[] TakeScreenshot()
    {
      try
      {
        var getMaxSide = "return Math.max(document.body.scroll{0}, document.body.offset{0}, document.documentElement.client{0}, document.documentElement.scroll{0}, document.documentElement.offset{0})";
        var scrollHeight = (Driver as IJavaScriptExecutor).ExecuteScript(string.Format(getMaxSide, "Height"));
        var scrollWidth = (Driver as IJavaScriptExecutor).ExecuteScript(string.Format(getMaxSide, "Width"));
        Driver.Manage().Window.Size = new Size(int.Parse(scrollWidth.ToString()), int.Parse(scrollHeight.ToString()));
        return (Driver as ITakesScreenshot).GetScreenshot().AsByteArray;
      }
      catch
      {
        return Array.Empty<byte>();
      }
    }

然后,您可以使用结果将其附加到例如魅力或NUnit测试结果:

 private void AttachScreenshot()
    {
      var screenshot = _browser?.TakeScreenshot();
      if (screenshot.Length > 0)
      {
        // add screenshot to test results
        var path = DateTime.Now.Ticks.ToString() + ".png";
        File.WriteAllBytes(path, screenshot);
        TestContext.AddTestAttachment(path, "screenshot");

        // attach screenshot to Allure report
        AllureLifecycle.Instance.AddAttachment("screenshot", "image/png", screenshot);
      }
    }

答案 8 :(得分:0)

更改浏览器高度并不总是有效。这是我使用的解决方案。它滚动页面并组成整页屏幕截图。

public static Image TakeFullPageScreenshot(this RemoteWebDriver driver, int maxHeight = 10000)
    {
        Bitmap fullPageScreenshot = null;
        using (var fullMs = new MemoryStream((driver.GetScreenshot()).AsByteArray)) { 
            fullPageScreenshot = Image.FromStream(fullMs) as Bitmap;
        }
        var originalPageOffset = driver.GetPageOffset();

        var prevPageOffset = 0;
        var currentPageOffset = 0;
        var scrollLength = (int)(driver.Manage().Window.Size.Height / 1.5);
        while (fullPageScreenshot.Height < maxHeight)
        {
            prevPageOffset = driver.GetPageOffset().Y;
                       
            driver.ScrollPageBy(0, scrollLength);
            System.Threading.Thread.Sleep(500);

            currentPageOffset = driver.GetPageOffset().Y;

            if (prevPageOffset == currentPageOffset)
            {
                break;
            }
            var pageMovedBy = currentPageOffset - prevPageOffset;
            using (var ms = new MemoryStream(driver.GetScreenshot().AsByteArray))
            {
                using (var viewPortScreenshot = Image.FromStream(ms) as Bitmap)
                {
                    var croppedScreenshot = CropBitmapAtRect(viewPortScreenshot, new Rectangle(0, viewPortScreenshot.Height - pageMovedBy, viewPortScreenshot.Width, pageMovedBy));
                    var newFullPage = AppendBitmap(fullPageScreenshot, croppedScreenshot);
                    fullPageScreenshot.Dispose();
                    fullPageScreenshot = newFullPage;
                }
            }
        }
        driver.ScrollPageTo(originalPageOffset.X, originalPageOffset.Y);
        return fullPageScreenshot;
    }

    public static Bitmap CropBitmapAtRect(Bitmap b, Rectangle r)
    {
        Bitmap nb = new Bitmap(r.Width, r.Height);
        using (Graphics g = Graphics.FromImage(nb))
        {
            g.DrawImage(b, -r.X, -r.Y);
            return nb;
        }
    }

    public static Bitmap AppendBitmap(Bitmap source, Bitmap target, int spacing = 0)
    {
        int w = Math.Max(source.Width, target.Width);
        int h = source.Height + target.Height + spacing;
        Bitmap bmp = new Bitmap(w, h);

        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.DrawImage(source, 0, 0);
            g.DrawImage(target, 0, source.Height + spacing);
        }

        return bmp;
    }

    public static void ScrollPageBy(this RemoteWebDriver driver, int x = 0, int y = 0)
    {
        driver.ExecuteScript(@"window.scroll(window.pageXOffset + arguments[0], window.pageYOffset + arguments[1]);", x, y);
    }

    public static void ScrollPageTo(this RemoteWebDriver driver, int x = 0, int y = 0)
    {
        driver.ExecuteScript(@"window.scroll(arguments[0], arguments[1]);", x, y);
    }

    public static Point GetPageOffset(this RemoteWebDriver driver)
    {
        var offsetArray = driver.ExecuteScript(@"return [window.pageXOffset, window.pageYOffset];") as ReadOnlyCollection<object>;
        var x = (long)offsetArray[0];
        var y = (long)offsetArray[1];
        return new Point((int)x, (int)y);
    }

答案 9 :(得分:0)

根据@Michal Kalous 的回答,我创建了一个 etension 类。 这也考虑了当前在 widows 中设置的字体大小和实际视口大小,并通过将 body.style.overflowY 设置为隐藏来移除垂直滚动条。

用法

RemoteWebDriver driver = new EdgeDriver();
driver.SetViewportSize(1200, 1200);

driver.Navigate().GoToUrl("https://www.bikereview.info/en/ktm-1290-super-duke-rr-innerhalb-von-48-minuten-ausverkauft.html");
Image tempImage = driver.TakeFullPageScreenshot();
tempImage.Save(@"c:\full.png", ImageFormat.Png);
driver.Close();
driver.Quit();

扩展类

using System;
using System.Drawing;
using System.IO;
using OpenQA.Selenium.Remote;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using OpenQA.Selenium;

namespace TestRenderHtmlToPng
{


    public static class RemoteWebDriverExtensions
    {

        public static Image TakeFullPageScreenshot(this RemoteWebDriver driver, int maxHeight = 10000)
        {

            //Screenshots depend on fontscaleing-property in windows
            double DpiScalingFactor = GetDpiScalingFactor();

            Bitmap fullPageScreenshot = null;
            using (var fullMs = new MemoryStream((driver.GetScreenshotOverflowHidden()).AsByteArray))
            {
                fullPageScreenshot = Image.FromStream(fullMs) as Bitmap;
            }
            var originalPageOffset = driver.GetPageOffset();

            var prevPageOffset = 0;
            var currentPageOffset = 0;
            var scrollLength = driver.GetWindowInnerHeight();

            while (fullPageScreenshot.Height < maxHeight)
            {
                prevPageOffset = driver.GetPageOffset().Y;

                driver.ScrollPageBy(0, scrollLength);
                System.Threading.Thread.Sleep(100);

                currentPageOffset = driver.GetPageOffset().Y;

                if (prevPageOffset == currentPageOffset)
                {
                    break;
                }
                var pageMovedBy = currentPageOffset - prevPageOffset;
                pageMovedBy = (int)(pageMovedBy * DpiScalingFactor);

                using (var ms = new MemoryStream(driver.GetScreenshotOverflowHidden().AsByteArray))
                {
                    Bitmap fullPageScreenshot1 = Image.FromStream(ms) as Bitmap;
                    using (var viewPortScreenshot = Image.FromStream(ms) as Bitmap)
                    {
                        var s = driver.Manage().Window.Size;

                        var croppedScreenshot = CropBitmapAtRect(viewPortScreenshot, new Rectangle(0, viewPortScreenshot.Height - pageMovedBy, viewPortScreenshot.Width, pageMovedBy));

                        var newFullPage = AppendBitmap(fullPageScreenshot, croppedScreenshot);

                        fullPageScreenshot.Dispose();
                        fullPageScreenshot = newFullPage;
                    }
                }
            }
            driver.ScrollPageTo(originalPageOffset.X, originalPageOffset.Y);
            return fullPageScreenshot;
        }



        private static Bitmap CropBitmapAtRect(Bitmap b, Rectangle r)
        {
            Bitmap nb = new Bitmap(r.Width, r.Height);
            using (Graphics g = Graphics.FromImage(nb))
            {
                g.DrawImage(b, -r.X, -r.Y);
                return nb;
            }
        }

        private static Bitmap AppendBitmap(Bitmap source, Bitmap target, int spacing = 0)
        {
            int w = Math.Max(source.Width, target.Width);
            int h = source.Height + target.Height + spacing;
            Bitmap bmp = new Bitmap(w, h);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.DrawImage(source, 0, 0);
                g.DrawImage(target, 0, source.Height + spacing);
            }

            return bmp;
        }

        private static Screenshot GetScreenshotOverflowHidden(this RemoteWebDriver driver)
        {
            driver.ExecuteScript(@" document.body.style.overflowY = ""hidden"";");
            var s = driver.GetScreenshot();
            driver.ExecuteScript(@" document.body.style.overflowY = """";");
            return s;
        }

        private static void ScrollPageBy(this RemoteWebDriver driver, int x = 0, int y = 0)
        {
            driver.ExecuteScript(@"window.scroll(window.pageXOffset + arguments[0], window.pageYOffset + arguments[1]);", x, y);
        }
        private static void ScrollPageTo(this RemoteWebDriver driver, int x = 0, int y = 0)
        {
            driver.ExecuteScript(@"window.scroll(arguments[0], arguments[1]);", x, y);
        }

        public static void SetViewportSize(this RemoteWebDriver driver, int width, int height)
        {
            var jsGetPadding = @"return [ window.outerWidth - window.innerWidth,window.outerHeight - window.innerHeight ];";
            var paddingArray = driver.ExecuteScript(jsGetPadding) as ReadOnlyCollection<object>;
            driver.Manage().Window.Size = new Size(width + int.Parse(paddingArray[0].ToString()), height + int.Parse(paddingArray[1].ToString()));

        }

        private static Point GetPageOffset(this RemoteWebDriver driver)
        {
            var offsetArray = driver.ExecuteScript(@"return [window.pageXOffset, window.pageYOffset];") as ReadOnlyCollection<object>;
            var x = int.Parse(offsetArray[0].ToString());
            var y = int.Parse(offsetArray[1].ToString().Split(',')[0]);
            return new Point((int)x, (int)y);
        }
        private static int GetWindowInnerHeight(this RemoteWebDriver driver)
        {
            var Value = driver.ExecuteScript(@"return [window.innerHeight];") as ReadOnlyCollection<object>;
            return int.Parse(Value[0].ToString());

        }

        [DllImport("gdi32.dll")]
        private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
        public enum DeviceCap
        {
            VERTRES = 10,
            DESKTOPVERTRES = 117,

            // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
            // https://stackoverflow.com/questions/5977445/how-to-get-windows-display-settings#answer-21450169
        }


        private static float GetDpiScalingFactor()
        {
            Graphics g = Graphics.FromHwnd(IntPtr.Zero);
            IntPtr desktop = g.GetHdc();
            int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
            int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

            float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;

            return ScreenScalingFactor; // 1.25 = 125%
        }

    }
}