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