【问题标题】:Selenium webdriver C# - Taking full page screenshotSelenium webdriver C# - 获取整页截图
【发布时间】:2023-03-09 23:14:01
【问题描述】:

谁能帮我用 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();

}

【问题讨论】:

  • 贴出你目前使用的代码。
  • 你认为什么是完整的浏览器页面?
  • 到底是什么问题?您的代码看起来不错。
  • 感谢您的回复。我看不到 URL 和浏览器的其他顶部。我之前可以使用 Selenium RC 获取整个页面。
  • 你需要网址栏等做什么?

标签: webdriver screenshot selenium-webdriver


【解决方案1】:

你可以使用这个包https://www.nuget.org/packages/Noksa.WebDriver.ScreenshotsExtensions/

为了截取整个页面,请使用 VerticalCombineDecorator:

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

【讨论】:

  • 我最近开始使用它,我喜欢它,但它似乎有时会出现内存问题,并且在生成 HTML 报告时会挂起
【解决方案2】:

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

【讨论】:

  • 谢谢大家的回答。
【解决方案3】:

我在我们的解决方案中使用了这个:

 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>();
      }
    }

然后您可以使用结果将其附加到例如Allure 或 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);
      }
    }

【讨论】:

    【解决方案4】:

    在截屏之前尝试将浏览器窗口的大小更改为很大。我的尺寸比宽度小 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);
        }
    

    【讨论】:

      【解决方案5】:

      你可以试试这个

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

      【讨论】:

      • 这是使用 selenium webdriver 和 phantomjs 截取屏幕截图。如果你想使用 firefox 或 chrome。您可以将 PhantomJSDriver() 更改为您希望使用的驱动程序。
      • @Salih 我能够使用((ITakesScreenshot)driver).GetScreenshot().SaveAsFile(); 方法获取屏幕截图,谢谢分享!
      【解决方案6】:

      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】:

        我记得 ((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);
        

        【讨论】:

          【解决方案8】:

          试试这个希望它对你有用。

          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;
                      }
                  }
          

          【讨论】:

            【解决方案9】:

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

            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);
                }
            

            【讨论】:

              【解决方案10】:

              根据@Michal Kalous 的回答,我创建了一个etension 课程。 这也考虑了当前在寡妇中设置的字体大小和实际视口大小,并通过将 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%
                      }
              
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2019-02-02
                • 1970-01-01
                • 2020-01-29
                • 1970-01-01
                • 1970-01-01
                • 2023-01-23
                • 1970-01-01
                • 2017-02-10
                • 2021-07-12
                相关资源
                最近更新 更多