如何使用Selenium和Java获取完整网页的屏幕截图



如何使用Selenium WebDriver截取整个网页的屏幕截图(整页屏幕截图),而不仅仅是部分(从上到下)?

我的代码:(Java 绑定)

System.setProperty("webdriver.chrome.driver","/home/alex/Downloads/chromedriver_linux64/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("http://google.com");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(RESULT_FILENAME));

关于如何解决这个问题的任何想法?

LE:我看到很多人对整页截图感兴趣,所以我想我可能会用一些积极的东西(银弹)来更新答案。

有相当多的Web测试框架可以(以最少的设置和工作量)生成整页屏幕截图。我来自NodeJS测试环境,所以我只能保证以下内容:WebdriverIO和Google的Puppeteer。

如果有人对使用WebdriverIO的简单方法感兴趣,请查看此答案。


简短的回答是否定的,你不能,如果你只使用硒(详细原因如下)。但是,您可以做的是充分利用设备的(监视器)视口。

因此,请使用ChromeOptions()启动浏览器实例(驱动程序),这是设置ChromeDriver特定功能的方法。我们可以做到以下几点:

  • 最大化窗口(使用--start-maximized开关);
  • 全屏(在 Windows 上F11键,在 Mac 上Control+Cmd+F键,使用--start-fullscreen开关)。
  • 注意:可在此处找到 Chrome 命令行开关的完整列表。

您的代码应如下所示:

// Setting your Chrome options (Desired capabilities)
ChromeOptions options = new ChromeOptions();
options.add_argument('--start-maximized');
options.add_argument('--start-fullscreen');
// Creating a driver instance with the previous capabilities
WebDriver driver = new ChromeDriver(options);
// Load page & take screenshot of full-screen page
driver.get("http://google.com");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

现在关于整页问题,所有驱动程序(chromedrivergeckodriverIEDriverEdgeDriver等)都在实现WebDriver W3C标准。因此,它们取决于WebDriver团队想要公开不同功能的功能的方式,在我们的例子中是"截屏"。

如果您阅读定义,它会清楚地说明以下内容:

"截屏"命令拍摄顶级浏览上下文的VIEWPORT的屏幕截图。

在传统方面,一些驱动程序能够生成整页屏幕截图(在此处阅读更多相关信息),例如旧的FirefoxDriver,IEDriver等。情况已不再如此,因为它们现在都(不折不扣地)实现了WebDriver W3C标准。

现在有一个简单的方法可以使用Selenium 4和Firefox来做到这一点。

byte[] imageBytes = ((FirefoxDriver)driver).getFullPageScreenshotAs(OutputType.BYTES);
Files.write(Paths.get(RESULT_FILENAME), imageBytes);

其他浏览器尚不支持getFullPageScreenshotAs()

看起来这篇文章建议 AShot 对我有用。此外,我使用以下代码成功地将整页屏幕截图嵌入到黄瓜报告中

scenario.embed(takeScreenShotAsByte(getWebDriver()), "image/png");
private static byte[] takeScreenShotAsByte(WebDriver webDriver) throws IOException {
return takeFullPageScreenShotAsByte(webDriver);
}
private static byte[] takeFullPageScreenShotAsByte(WebDriver webDriver) throws IOException {
Screenshot fpScreenshot = new AShot().shootingStrategy(ShootingStrategies.viewportPasting(1000))
.takeScreenshot(webDriver);
BufferedImage originalImage = fpScreenshot.getImage();
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
ImageIO.write(originalImage, "png", baos);
baos.flush();
return baos.toByteArray();
}
}

我找到了一个教程 http://www.softwaretestingmaterial.com/how-to-capture-full-page-screenshot-using-selenium-webdriver/对于 maven 用户:请记住从 https://mvnrepository.com/artifact/ru.yandex.qatools.ashot/ashot 添加依赖项 当我测试这个脚本时,我有大图片,无法在浏览器中打开(太大或损坏)。

所以也许有人知道任何脚本,最后一个使用的定位器的重点页面?

这是我使用 C# 获取全屏屏幕截图的示例,但只需更改:

string _currentPath = Path.GetDirectoryName(Assembly.GetAssembly(typeof(One of your objects)).Location) + @"Attachs";
var filePath = _currentPath + sSName;
if (!Directory.Exists(_currentPath))
Directory.CreateDirectory(_currentPath);
Dictionary<string, Object> metrics = new Dictionary<string, Object>();
metrics["width"] = _driver.ExecuteScript("return Math.max(window.innerWidth,document.body.scrollWidth,document.documentElement.scrollWidth)");
metrics["height"] = _driver.ExecuteScript("return Math.max(window.innerHeight,document.body.scrollHeight,document.documentElement.scrollHeight)");
metrics["deviceScaleFactor"] = (double)_driver.ExecuteScript("return window.devicePixelRatio");
metrics["mobile"] = _driver.ExecuteScript("return typeof window.orientation !== 'undefined'");
_driver.ExecuteChromeCommand("Emulation.setDeviceMetricsOverride", metrics);
_driver.GetScreenshot().SaveAsFile(filePath, ScreenshotImageFormat.Png);
_driver.ExecuteChromeCommand("Emulation.clearDeviceMetricsOverride", new Dictionary<string, Object>());
_driver.Close();

可以在无头模式下启动Chrome,然后将窗口大小设置为与页面正文相同的高度。

由于无头浏览器的高度不依赖于显示器尺寸,因此您可以使用此无头模式获取在Chrome浏览器中呈现的完整屏幕截图。

使用硒运行的无头Chrome的最佳答案似乎显示了使用java在无头模式下启动Chrome的正确方法。我使用 python 绑定,但答案看起来与我所做的非常相似。

这是相关的部分。此代码应在启动 ChromeDrive 实例之前删除。

ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--headless");
ChromeDriver driver = new ChromeDriver(chromeOptions);

如果在无头浏览器中运行chrome不是一个可行的选择,那么您将不得不使用Firefox或IE。这两个浏览器都会给你一个完整的截图

以下是使用DevTools + Chromedriver执行此操作的一种方法:

private String takeScreenshot(ChromeDriver driver, boolean fullscreen) {
if (fullscreen) {
Map<String, Object> layoutMetrics = driver.executeCdpCommand("Page.getLayoutMetrics", Collections.emptyMap());
Map<String, Object> screenshotConfig = Maps.newHashMap();
screenshotConfig.put("captureBeyondViewport", true);
screenshotConfig.put("fromSurface", true);
Map contentSize = (Map)layoutMetrics.get("contentSize");
screenshotConfig.put("clip", ImmutableMap.of(
"width", contentSize.get("width"),
"height", contentSize.get("height"),
"x", 0,
"y", 0,
"scale", 1
));
Map<String, Object> base64PngResult = driver.executeCdpCommand("Page.captureScreenshot", screenshotConfig);
return (String)base64PngResult.get("data");
}
return driver.getScreenshotAs(OutputType.BASE64);
}

不使用第三方库的 Java 代码:

int bodyHeight = webDriver.findElement(By.tagName("body")).getSize().getHeight();
int windowChromeHeight = (int) (long) webDriver.executeScript("return window.outerHeight - window.innerHeight");
Dimension size = new Dimension(webDriver.manage().window().getSize().getWidth(), bodyHeight + windowChromeHeight);
webDriver.executeScript("window.scrollTo(0, 0);");
webDriver.manage().window().setSize(size);

File screenshotFile = new File("screenshot.png");
Files.write(screenshotFile.toPath(), webDriver.getScreenshotAs(OutputType.BYTES));

对于某些页面,我需要截取页面开头和结尾的屏幕截图。所以我曾经截取 2 张屏幕截图:

public static String javaIoTmpDir = System.getProperty("java.io.tmpdir"); //tmp dir
//create screenshot
driver.manage().window().fullscreen();
//For large pages - body over 850 px highh - take addition screenshot of the end of page
if (driver.findElements(By.id("panel_body")).size()>0) {
WebElement body = driver.findElement(By.id("panel_body"));
int bodyHight = body.getSize().getHeight();
if (bodyHight > 850) {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_END);
robot.keyRelease(KeyEvent.VK_END);
Thread.sleep(1000);
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
String timePictureEnd = javaIoTmpDir+"\scr_"+String.valueOf(System.currentTimeMillis())+getClass().toString().substring(getClass().toString().lastIndexOf(".qa.")+3)+".png";
FileUtils.copyFile(scrFile, new File(timePictureEnd));
robot.keyPress(KeyEvent.VK_HOME); //back to top page for next screen
robot.keyRelease(KeyEvent.VK_HOME);
Thread.sleep(1000);
}
}
String timePicture = javaIoTmpDir+"\scr_"+String.valueOf(System.currentTimeMillis())+getClass().toString().substring(getClass().toString().lastIndexOf(".qa.")+3)+".png";
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(timePicture));

您可以使用Phantomjs来实现它。

这是我的java代码:

public class PhantomjsTest {
public static void main(String[] args) {
try {
long start=System.currentTimeMillis();
//The page you want to screenshot
String targetUrl="https://www.iqiyi.com/";
//File path
String targetImg="iqiyi.png";
String command = "/Users/hetiantian/SoftWares/phantomjs/bin/phantomjs /Users/hetiantian/SoftWares/phantomjs/examples/rasterize.js "+targetUrl + " " +targetImg;
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println((System.currentTimeMillis()-start));
} catch (Exception e) {
e.printStackTrace();
}

}
}

因此,您可以获得Phantomjs的完整网页的屏幕截图。当您使用Phantomjs获取完整的屏幕截图时,您需要先下载Phantomjs。然后运行Phantomjs脚本进行屏幕截图。更多关于它的信息,你可以参考 phantomjs.org。

这里描述的选项在我的环境中都不适合我(go lang,chromedriver,web驱动程序的fedesog实现) 最终来到我的是缩小!此方法适用于不太长的页面,在这些页面中,缩小是有意义的。

我认为这可能与java或任何其他使用selenium的语言有关,因此请在此处发布给在任何编程语言中遇到此问题的任何人:) 以下 JavaScript 代码片段允许设置缩放级别:

document.body.style.zoom = '0.5'

其中 0.5 是您想要的缩放级别。它可以根据实际页面大小动态计算,可以使用以下方法检索:

document.body.scrollHeight

document.body.scrollWidth

如上所述,并按如下方式执行:

webDriver.executeScript(...)

在爪哇或

session.ExecuteScript(...)

在戈朗使用Fedesog或类似的WebDriver框架

这是我找到的最简单的解决方案,我想大多数时候应该有效:

在无外设模式下,您可以将视口设置为几乎任何所需的大小,而与任何现有的物理屏幕大小无关。例如:

final ChromeOptions options = new ChromeOptions().setHeadless(true).addArguments("window-size=1200,3000");
driver = new RemoteWebDriver(remoteAddress, options);

请注意,您可以使用较大的高度来尝试适合整个页面。

File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\RESULT_FILENAME.png"));

试试这个

最新更新