Selenium - 通过 BrowserStack 获取整页移动屏幕截图
Selenium - Taking full-page mobile screenshots via BrowserStack
我创建了一个工具,可以在许多桌面和设备配置上的 URL 列表上截取整页屏幕截图。在桌面上,这一切都可以顺利进行,我得到了整页屏幕截图,在所有浏览器和 OS 版本上都没有问题。
尝试在移动设备上执行此操作时出现问题,我猜这是由于我 运行 使用的设备的像素比率所致。
我的方法获取页面的总高度和宽度,以及视口的高度和宽度,基本上获取视口的图像,在必要时滚动,然后在最后,将所有这些拼接成一张图片。
但是,根据我通过 JavaScript 检索的像素比例,屏幕截图从未正确捕获并且无法正确滚动 and/or 未捕获整个页面.横向没关系,它总是高度。好像计算滚动不正确
令我震惊的是,我在网上找不到任何 post 有相同或相似问题的人。所以要么我把它复杂化了,它是如此微不足道以至于它永远不需要 post,要么这比我想象的要难得多,人们没有这样做是有充分理由的
如果有人有任何想法或想法,他们将不胜感激
谢谢!
该方法的代码如下:
public Image GetEntireScreenshot(ArrayList hiddenElementListAfterFirstViewport = null, bool isMobile = false)
{
var pixelRatio = 1;
if (isMobile) pixelRatio = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return window.devicePixelRatio");
// Size of page
var totalWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.offsetWidth") * pixelRatio);
var totalHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.parentNode.scrollHeight") * pixelRatio);
// Size of the viewport
var viewportWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.clientWidth") * pixelRatio);
var viewportHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return window.innerHeight") * pixelRatio);
var screenshot = (ITakesScreenshot)driver;
((IJavaScriptExecutor)driver).ExecuteScript("window.scrollTo(0, 0)");
if (hiddenElementListAfterFirstViewport != null)
{
foreach (string hiddenElementXPath in hiddenElementListAfterFirstViewport)
{
IList<IWebElement> elements = driver.FindElements(By.XPath(hiddenElementXPath));
foreach (var element in elements)
{
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.visibility='hidden'", element);
}
}
}
if (totalWidth <= viewportWidth && totalHeight <= viewportHeight) return ScreenshotToImage(screenshot.GetScreenshot());
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
rectangles.Add(new Rectangle(x, y, newWidth, newHeight));
}
}
var stitchedImage = new Bitmap(totalWidth, totalHeight);
var previous = Rectangle.Empty;
foreach (var rectangle in rectangles)
{
// Calculate scrolling (if needed)
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right}, {rectangle.Bottom - previous.Bottom})");
// 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(ScreenshotToImage(screenshot.GetScreenshot()), rectangle, sourceRectangle, GraphicsUnit.Pixel);
}
previous = rectangle;
}
return stitchedImage;
}
您可以使用 ShutterBug 等工具在移动设备上捕获整页屏幕截图,http://automationtesting.in/take-full-page-screenshot-using-shutterbug/
我解决了这个问题,post如果有同样问题的人看到这个 post:
问题出在代码的滚动部分:
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right}, {rectangle.Bottom - previous.Bottom})");
我滚动的是之前乘以像素比率的值,这意味着它们太多了,因为滚动 X 和 Y 值不受设备像素比率的影响。
因此,代码应该是:
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({(rectangle.Right - previous.Right) / pixelRatio}, {(rectangle.Bottom - previous.Bottom) / pixelRatio})");
我创建了一个工具,可以在许多桌面和设备配置上的 URL 列表上截取整页屏幕截图。在桌面上,这一切都可以顺利进行,我得到了整页屏幕截图,在所有浏览器和 OS 版本上都没有问题。
尝试在移动设备上执行此操作时出现问题,我猜这是由于我 运行 使用的设备的像素比率所致。
我的方法获取页面的总高度和宽度,以及视口的高度和宽度,基本上获取视口的图像,在必要时滚动,然后在最后,将所有这些拼接成一张图片。
但是,根据我通过 JavaScript 检索的像素比例,屏幕截图从未正确捕获并且无法正确滚动 and/or 未捕获整个页面.横向没关系,它总是高度。好像计算滚动不正确
令我震惊的是,我在网上找不到任何 post 有相同或相似问题的人。所以要么我把它复杂化了,它是如此微不足道以至于它永远不需要 post,要么这比我想象的要难得多,人们没有这样做是有充分理由的
如果有人有任何想法或想法,他们将不胜感激
谢谢!
该方法的代码如下:
public Image GetEntireScreenshot(ArrayList hiddenElementListAfterFirstViewport = null, bool isMobile = false)
{
var pixelRatio = 1;
if (isMobile) pixelRatio = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return window.devicePixelRatio");
// Size of page
var totalWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.offsetWidth") * pixelRatio);
var totalHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.parentNode.scrollHeight") * pixelRatio);
// Size of the viewport
var viewportWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.clientWidth") * pixelRatio);
var viewportHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return window.innerHeight") * pixelRatio);
var screenshot = (ITakesScreenshot)driver;
((IJavaScriptExecutor)driver).ExecuteScript("window.scrollTo(0, 0)");
if (hiddenElementListAfterFirstViewport != null)
{
foreach (string hiddenElementXPath in hiddenElementListAfterFirstViewport)
{
IList<IWebElement> elements = driver.FindElements(By.XPath(hiddenElementXPath));
foreach (var element in elements)
{
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.visibility='hidden'", element);
}
}
}
if (totalWidth <= viewportWidth && totalHeight <= viewportHeight) return ScreenshotToImage(screenshot.GetScreenshot());
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
rectangles.Add(new Rectangle(x, y, newWidth, newHeight));
}
}
var stitchedImage = new Bitmap(totalWidth, totalHeight);
var previous = Rectangle.Empty;
foreach (var rectangle in rectangles)
{
// Calculate scrolling (if needed)
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right}, {rectangle.Bottom - previous.Bottom})");
// 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(ScreenshotToImage(screenshot.GetScreenshot()), rectangle, sourceRectangle, GraphicsUnit.Pixel);
}
previous = rectangle;
}
return stitchedImage;
}
您可以使用 ShutterBug 等工具在移动设备上捕获整页屏幕截图,http://automationtesting.in/take-full-page-screenshot-using-shutterbug/
我解决了这个问题,post如果有同样问题的人看到这个 post:
问题出在代码的滚动部分:
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right}, {rectangle.Bottom - previous.Bottom})");
我滚动的是之前乘以像素比率的值,这意味着它们太多了,因为滚动 X 和 Y 值不受设备像素比率的影响。
因此,代码应该是:
if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({(rectangle.Right - previous.Right) / pixelRatio}, {(rectangle.Bottom - previous.Bottom) / pixelRatio})");