Как получить скриншот полной веб-страницы, используя Selenium и Java?
Как сделать скриншот для всей веб-страницы, а не только частичной сверху, используя Selenium WebDriver?
Мой Java-код Selenium WebDriver выглядит следующим образом:
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));
Есть идеи?
13 ответов
Короткий ответ - НЕТ, ВЫ НЕ МОЖЕТЕ (подробное объяснение ниже). Но то, что вы можете сделать, это максимально использовать область просмотра вашего устройства (монитора).
Итак, запустите ваш экземпляр браузера (драйвер), используя ChromeOptions()
, который является методом для настройки возможностей ChromeDriver. Мы можем сделать следующее:
- развернуть окно (используя
--start-maximized
переключатель); - перейти на полный экран (
F11
ключ в Windows,Control+Cmd+F
на Mac, используя--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);
Теперь по поводу проблемы полной страницы, все драйверы (chromedriver
, geckodriver
, IEDriver
, EdgeDriver
и т. д.) внедряем стандарт WebDriver W3C. Таким образом, они зависят от того, как команда WebDriver хочет показать функциональность различных функций, в нашем случае, "Снимок экрана".
Если вы читаете определение, оно четко гласит следующее:
Команда Take Screenshot делает снимок экрана VIEWPORT контекста верхнего уровня.
Устаревшие версии, некоторые драйверы могли создавать снимок экрана на всю страницу (подробнее об этом здесь), например старый FirefoxDriver, IEDriver и т. Д. Это уже не так, поскольку все они теперь реализуют (буквально) WebDriver Стандарт W3C.
Теперь есть простой способ сделать это с помощью Selenium 4 и Firefox.
byte[] imageBytes = ((FirefoxDriver)driver).getFullPageScreenshotAs(OutputType.BYTES);
Files.write(Paths.get(RESULT_FILENAME), imageBytes);
Другие браузеры не поддерживают
getFullPageScreenshotAs()
еще.
Похоже, эта статья, в которой говорится, что 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();
}
}
Вот как это сделать с помощью 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);
}
Я нашел учебник 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 без головы с селеном, похоже, показывает правильный способ запустить Chrome в режиме без головы с помощью java. Я работаю с привязками Python, но ответ очень похож на то, что делаю я.
Это важная часть. Этот код должен быть выполнен до того, как вы запустите экземпляр ChromeDriver.
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--headless");
ChromeDriver driver = new ChromeDriver(chromeOptions);
Если запуск Chrome в безголовом браузере не является жизнеспособным вариантом, вам придется использовать Firefox или IE. Оба этих браузера предоставят вам полный скриншот.
Код 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 для скриншота. Подробнее об этом вы можете сослаться на http://phantomjs.org/.
Это самое простое решение, которое я нашел, которое, я думаю, должно работать в большинстве случаев:
В безголовом режиме вы можете установить область просмотра практически любого размера, который вы хотите, независимо от любого существующего физического размера экрана. Например:
final ChromeOptions options = new ChromeOptions().setHeadless(true).addArguments("window-size=1200,3000");
driver = new RemoteWebDriver(remoteAddress, options);
Обратите внимание, что вы можете использовать большую высоту, чтобы попытаться уместить всю страницу.
Ни один из описанных здесь вариантов не работал у меня в моей среде (go lang, chromedriver, реализация веб-драйвера fedesog). В конце концов мне пришло в голову уменьшить масштаб! Этот подход может работать для не слишком длинных страниц, для которых имеет смысл уменьшить масштаб.
Я думаю, что это может быть актуально для java или любого другого языка, использующего селен, поэтому размещаю его здесь для всех, кто сталкивается с этой проблемой на любом языке программирования :) Следующий фрагмент кода javascript позволяет установить уровень масштабирования:
document.body.style.zoom = '0.5'
Где 0,5 — это желаемый уровень масштабирования. Его можно рассчитать динамически на основе фактического размера страницы, который можно получить с помощью:
document.body.scrollHeight
и
document.body.scrollWidth
как упомянуто выше, и выполняется как:
webDriver.executeScript(...)
в java или
session.ExecuteScript(...)
в golang с использованием fedesog или аналогичной среды веб-драйвера
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\RESULT_FILENAME.png"));
Попробуй это