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

时间:2017-05-20 12:12:37

标签: java selenium selenium-webdriver webdriver screenshot

如何使用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));

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

10 个答案:

答案 0 :(得分:13)

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

有相当多的网络测试框架可以(以最少的设置和努力)生成 整页截图 。我来自NodeJS测试环境,所以我只能保证以下内容:WebdriverIO&谷歌的Puppeteer

如果有人对使用WebdriverIO的简单方法感兴趣,请检查this answer。

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

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

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

您的代码应如下所示:

// 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团队希望公开不同功能的功能的方式,在我们的例子中,'Take Screenshot'

如果你阅读了这个定义,它会清楚地说明以下内容:

  

Take Screenshot命令获取顶级浏览上下文 VIEWPORT 的屏幕截图。

传统方面,一些驱动程序能够生成整页截图(阅读更多关于它here),就像旧的FirefoxDriver,IEDriver等一样。现在不再是这样了,因为他们现在都在实施(致信)WebDriver W3C标准。

答案 1 :(得分:5)

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

所以也许有人知道任何脚本,它将页面集中在上次使用的定位器上?

答案 2 :(得分:2)

像这样的article暗示AShot对我有用。另外,我使用以下代码成功将整个屏幕截图嵌入了Cucumber报告中

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

答案 3 :(得分:2)

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

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

Headless Chrome run with selenium的最高答案似乎显示了使用Java在无头模式下启动Chrome的正确方法。我使用python绑定,但是答案看起来与我的操作非常相似。

这是相关部分。在启动ChromeDriver实例之前,应该先执行此代码。

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

ChromeDriver driver = new ChromeDriver(chromeOptions);

如果在无头浏览器中运行chrome不可行,则必须使用Firefox或IE。这两种浏览器都会为您提供完整的屏幕截图

答案 4 :(得分:1)

对于某些页面,我需要截取页面的开头和结尾的截图。所以我用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));

答案 5 :(得分:1)

您可以使用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

答案 6 :(得分:1)

现在有一种使用 Selenium 4 和 Firefox 的简单方法。

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

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

答案 7 :(得分:0)

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

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

答案 8 :(得分:0)

不使用第三方库的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));

答案 9 :(得分:-7)

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

试试这个