如何使用Selenium WebDriver和Java全屏幕截取可滚动网页的屏幕截图?

7

现有的代码仅截取可见屏幕的屏幕截图。我正在使用 Chromedriver

  System.setProperty("webdriver.chrome.driver", "D:/chromedriver/chromedriver.exe");
  WebDriver driver = new ChromeDriver();
  driver.get("http://www.bbc.com");       
  driver.manage().window().maximize();
  System.out.println(driver.getTitle());
  File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
  FileUtils.copyFile(scrFile, new File("D:/chromedriver/scr3.png"));
  driver.close();

1
我猜这不可能实现,因为Selenium只能与可见的Web元素交互。 - Jainish Kapadia
您能否手动截取由于滚动条而不可见的页面截图?因为要查看页面的这些部分,您需要手动滚动。如果不能,则如何使用Selenium实现它? - Shoaib Akhtar
2
@ShoaibAkhtar selenium IDE有一个命令(captureEntirePageScreenshot),可以截取整个页面(可滚动页面)的屏幕截图,那么为什么在webdriver中无法实现呢? - Sarthak Srivastava
@SarthakSrivastava 那张图片上的滚动条是可以滚动的吗?你想要生成带有滚动条的截图,并且在该截图中应该能够滚动滚动条。我猜这就是你的需求。如果是的话,那么我认为即使使用 Selenium IDE 中的 captureEntirePageScreenshot 也不可能实现。或者你的需求是其他什么? - Shoaib Akhtar
8个回答

3
请找到下面的代码,您可以滚动并截取尽可能多的屏幕截图。注意元素仍然是Webelement类型,请存储它们并相对滚动。您可以根据需要滚动以获取所需的屏幕截图数量。
driver.get("http://www.bbc.com");       
driver.manage().window().maximize();
System.out.println(driver.getTitle());
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:/chromedriver/scr3.png"));  
WebElement elements = driver.findElement(By.xpath(".//*[@id='page']/section[6]/div/div/div[1]/ul/li[3]/div/div[2]/h3/a"));    
Thread.sleep(3000L);
JavascriptExecutor js = (JavascriptExecutor) driver;
int yPosition = elements.getLocation().getY();
js.executeScript("window.scroll (0, " + yPosition + ") ");       
Thread.sleep(3000L);         
File scrFile1 = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile1, new File("D:/chromedriver/scr4.png"));
driver.close();

1
你有没有一个只有一个 png 文件(合并后)的解决方案? - Stéphane GRILLON

2
使用Shutterbug,简单明了。
public byte[] shootPage() throws IOException {
    BufferedImage image = Shutterbug.shootPage(driver, ScrollStrategy.WHOLE_PAGE).getImage();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    ImageIO.write(image, "png", outputStream);
    return outputStream.toByteArray();
}

1

1
要截取完整网页的屏幕截图,我们需要使用一个名为“aShot”的第三方实用程序。 aShot是一个WebDriver Schreenshot实用程序,我们可以使用它来拍摄整个网页以及单个WebElement的屏幕截图。为此,我们必须下载aShot jar文件并将其与Selenium jar文件一起添加到项目中。

1
您可以尝试这种方法。希望它会有用:-
public static void takeFullPageScreenShot(WebDriver driver) throws IOException {

    JavascriptExecutor jsExec = (JavascriptExecutor)driver;

    jsExec.executeScript("window.scrollTo(0, 0);"); //Scroll To Top

    Long innerHeight = (Long) jsExec.executeScript("return window.innerHeight;");
    Long scroll = innerHeight;

    Long scrollHeight = (Long) jsExec.executeScript("return document.body.scrollHeight;"); 

    scrollHeight = scrollHeight + scroll;

    do{

        File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        //Unique File Name For Each Screenshot
        File destination = new File("E://screenshots//"+String.join("_", 
        LocalDateTime.now().toString().split("[^A-Za-z0-9]"))+".jpg");

        FileUtils.copyFile(screenshot, destination));

        jsExec.executeScript("window.scrollTo(0, "+innerHeight+");");

        innerHeight = innerHeight + scroll;

    }while(scrollHeight >= innerHeight);
}


Or,
  File screenshot = 
  driver.findElement(By.tagName("body")).getScreenshotAs(OutputType.FILE);
  File destination = new File("E://screenshots//"+String.join("_", 
  LocalDateTime.now().toString().split("[^A-Za-z0-9]"))+".jpg");
  FileUtils.copyFile(screenshot, destination));

0

这是对@kwishna答案的一个进阶,将屏幕截图拼接成单个图像:

    public void takeFullPageScreenShot(WebDriver driver) throws IOException {
        JavascriptExecutor jsExec = (JavascriptExecutor) driver;
        jsExec.executeScript("window.scrollTo(0, 0);");
        Long innerHeight = (Long) jsExec.executeScript("return window.innerHeight;");
        Long scroll = innerHeight;
        Long scrollHeight = (Long) jsExec.executeScript("return document.body.scrollHeight;");

        scrollHeight = scrollHeight + scroll;

        List<byte[]> images = new ArrayList<>();

        do {
            byte[] screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
            images.add(screenshot);
            jsExec.executeScript("window.scrollTo(0, "+innerHeight+");");
            innerHeight = innerHeight + scroll;
        } while (scrollHeight >= innerHeight);

        BufferedImage result = null;
        Graphics g = null;

        int x = 0, y = 0;
        for(byte[] image : images){
            InputStream is = new ByteArrayInputStream(image);
            BufferedImage bi = ImageIO.read(is);
            if (result == null) {
                // Lazy init so we can infer height and width
                result = new BufferedImage(
                        bi.getWidth(), bi.getHeight() * images.size(),
                        BufferedImage.TYPE_INT_RGB);
                g = result.getGraphics();
            }
            g.drawImage(bi, x, y, null);
            y += bi.getHeight();
        }
        ImageIO.write(result,"png",new File("result.png"));
    }

0

试试这段代码。AB D 上面的回答有一些逻辑错误,下面已经解决了:

public static void takeFullPageScreenShot(WebDriver driver) throws IOException {

    JavascriptExecutor jsExec = (JavascriptExecutor)driver;

    //Returns a Long, Representing the Height of the window’s content area.
    Long windowHeight = (Long) jsExec.executeScript("return window.innerHeight;");

    //Returns a Long, Representing the Height of the complete WebPage a.k.a. HTML document.
    Long webpageHeight = (Long) jsExec.executeScript("return document.body.scrollHeight;"); 

    //Marker to keep track of the current position of the scroll point
    //Long currentWindowScroll = Long.valueOf(0);
    //Using java's boxing feature to create a Long object from native long value.

    Long currentWindowScroll = 0L;

    do{
        //System.out.println(windowHeight + ", " + webpageHeight + ", " + currentWindowScroll);

        jsExec.executeScript("window.scrollTo(0, " + currentWindowScroll + ");");

        Actions act = new Actions(driver);
        act.pause(5000).perform();

        File tempScreenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        //Unique File Name For Each Screenshot
        File destination = new File("C:\\core_java\\DemoScreenShot\\" + String.join("_", LocalDateTime.now().toString().split("[^A-Za-z0-9]"))+ ".png");

        Files.copy(tempScreenshot, destination);
        currentWindowScroll = currentWindowScroll + windowHeight;

    }while(currentWindowScroll <= webpageHeight);
}

0
在Selenium 4中,FirefoxDriver提供了一个getFullPageScreenshotAs方法,可以处理垂直和水平滚动,以及固定元素(例如导航栏)。其他驱动程序目前还没有这个功能。
System.setProperty("webdriver.gecko.driver", "path/to/geckodriver");
final FirefoxOptions options = new FirefoxOptions();
// set options...
final FirefoxDriver driver = new FirefoxDriver(options);
driver.get("https://stackoverflow.com/");
File fullScreenshotFile = driver.getFullPageScreenshotAs(OutputType.FILE);
// File will be deleted once the JVM exits, so you should copy it

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接