- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想使用 HtmlUnitDriver 截取页面的屏幕截图我遇到了这个 Link这个人制作了一个自定义 HTML 单元驱动程序来截取屏幕截图。但不幸的是,在实现时我遇到了一个异常(exception)。
“线程“main”中的异常 java.lang.ClassCastException:[B 无法转换为 java.io.File 在 Test.main(Test.java:39)"
我的代码如下-
import java.io.File;
import java.io.IOException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import com.gargoylesoftware.htmlunit.BrowserVersion;
public class Test extends ScreenCaptureHtmlUnitDriver {
public static void main(String[] args) throws InterruptedException, IOException {
WebDriver driver = new ScreenCaptureHtmlUnitDriver(BrowserVersion.FIREFOX_38);
driver.get("https://www.google.com/?gws_rd=ssl");
try{
File scrFile = ((ScreenCaptureHtmlUnitDriver) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:\\TEMP.PNG"));
}catch (Exception e) {
e.printStackTrace();
}
}
}
我正在使用的 HtmlUnit 驱动程序(链接中的那个)是这个-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.internal.Base64Encoder;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class ScreenCaptureHtmlUnitDriver extends HtmlUnitDriver implements TakesScreenshot {
private static Map<String, byte[]> imagesCache = Collections.synchronizedMap(new HashMap<String, byte[]>());
private static Map<String, String> cssjsCache = Collections.synchronizedMap(new HashMap<String, String>());
// http://stackoverflow.com/questions/4652777/java-regex-to-get-the-urls-from-css
private final static Pattern cssUrlPattern = Pattern.compile("background(-image)?[\\s]*:[^url]*url[\\s]*\\([\\s]*([^\\)]*)[\\s]*\\)[\\s]*");// ?<url>
public ScreenCaptureHtmlUnitDriver() {
super();
}
public ScreenCaptureHtmlUnitDriver(boolean enableJavascript) {
super(enableJavascript);
}
public ScreenCaptureHtmlUnitDriver(Capabilities capabilities) {
super(capabilities);
}
public ScreenCaptureHtmlUnitDriver(BrowserVersion version) {
super(version);
DesiredCapabilities var = ((DesiredCapabilities) getCapabilities());
var.setCapability(CapabilityType.TAKES_SCREENSHOT, true);
}
//@Override
@SuppressWarnings("unchecked")
public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
byte[] archive = new byte[0];
try {
archive = downloadCssAndImages(getWebClient(), (HtmlPage) getCurrentWindow().getEnclosedPage());
} catch (Exception e) {
}
if(target.equals(OutputType.BASE64)){
return target.convertFromBase64Png(new Base64Encoder().encode(archive));
}
if(target.equals(OutputType.BYTES)){
return (X) archive;
}
return (X) archive;
}
// http://stackoverflow.com/questions/2244272/how-can-i-tell-htmlunits-webclient-to-download-images-and-css
protected byte[] downloadCssAndImages(WebClient webClient, HtmlPage page) throws Exception {
WebWindow currentWindow = webClient.getCurrentWindow();
Map<String, String> urlMapping = new HashMap<String, String>();
Map<String, byte[]> files = new HashMap<String, byte[]>();
WebWindow window = null;
try {
window = webClient.getWebWindowByName(page.getUrl().toString()+"_screenshot");
webClient.getPage(window, new WebRequest(page.getUrl()));
} catch (Exception e) {
window = webClient.openWindow(page.getUrl(), page.getUrl().toString()+"_screenshot");
}
String xPathExpression = "//*[name() = 'img' or name() = 'link' and (@type = 'text/css' or @type = 'image/x-icon') or @type = 'text/javascript']";
List<?> resultList = page.getByXPath(xPathExpression);
Iterator<?> i = resultList.iterator();
while (i.hasNext()) {
try {
HtmlElement el = (HtmlElement) i.next();
String resourceSourcePath = el.getAttribute("src").equals("") ? el.getAttribute("href") : el
.getAttribute("src");
if (resourceSourcePath == null || resourceSourcePath.equals(""))
continue;
URL resourceRemoteLink = page.getFullyQualifiedUrl(resourceSourcePath);
String resourceLocalPath = mapLocalUrl(page, resourceRemoteLink, resourceSourcePath, urlMapping);
urlMapping.put(resourceSourcePath, resourceLocalPath);
if (!resourceRemoteLink.toString().endsWith(".css")) {
byte[] image = downloadImage(webClient, window, resourceRemoteLink);
files.put(resourceLocalPath, image);
} else {
String css = downloadCss(webClient, window, resourceRemoteLink);
for (String cssImagePath : getLinksFromCss(css)) {
URL cssImagelink = page.getFullyQualifiedUrl(cssImagePath.replace("\"", "").replace("\'", "")
.replace(" ", ""));
String cssImageLocalPath = mapLocalUrl(page, cssImagelink, cssImagePath, urlMapping);
files.put(cssImageLocalPath, downloadImage(webClient, window, cssImagelink));
}
files.put(resourceLocalPath, replaceRemoteUrlsWithLocal(css, urlMapping)
.replace("resources/", "./").getBytes());
}
} catch (Exception e) {
}
}
String pagesrc = replaceRemoteUrlsWithLocal(page.getWebResponse().getContentAsString(), urlMapping);
files.put("page.html", pagesrc.getBytes());
webClient.setCurrentWindow(currentWindow);
return createZip(files);
}
String downloadCss(WebClient webClient, WebWindow window, URL resourceUrl) throws Exception {
if (cssjsCache.get(resourceUrl.toString()) == null) {
cssjsCache.put(resourceUrl.toString(), webClient.getPage(window, new WebRequest(resourceUrl))
.getWebResponse().getContentAsString());
}
return cssjsCache.get(resourceUrl.toString());
}
byte[] downloadImage(WebClient webClient, WebWindow window, URL resourceUrl) throws Exception {
if (imagesCache.get(resourceUrl.toString()) == null) {
imagesCache.put(
resourceUrl.toString(),
IOUtils.toByteArray(webClient.getPage(window, new WebRequest(resourceUrl)).getWebResponse()
.getContentAsStream()));
}
return imagesCache.get(resourceUrl.toString());
}
public static byte[] createZip(Map<String, byte[]> files) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zipfile = new ZipOutputStream(bos);
Iterator<String> i = files.keySet().iterator();
String fileName = null;
ZipEntry zipentry = null;
while (i.hasNext()) {
fileName = i.next();
zipentry = new ZipEntry(fileName);
zipfile.putNextEntry(zipentry);
zipfile.write(files.get(fileName));
}
zipfile.close();
return bos.toByteArray();
}
List<String> getLinksFromCss(String css) {
List<String> result = new LinkedList<String>();
Matcher m = cssUrlPattern.matcher(css);
while (m.find()) { // find next match
result.add( m.group(2));
}
return result;
}
String replaceRemoteUrlsWithLocal(String source, Map<String, String> replacement) {
for (String object : replacement.keySet()) {
// background:url(http://org.com/images/image.gif)
source = source.replace(object, replacement.get(object));
}
return source;
}
String mapLocalUrl(HtmlPage page, URL link, String path, Map<String, String> replacementToAdd) throws Exception {
String resultingFileName = "resources/" + FilenameUtils.getName(link.getFile());
replacementToAdd.put(path, resultingFileName);
return resultingFileName;
}
}
更新
Andrew 提供的代码有效——但我想知道是否有一种方法可以让我们只下载选定的资源。例如 this website 我想只下载验证码图像那些id是“//*[@id='cimage']”因为下载所有资源需要很长时间。有没有一种方法可以让我们只下载特定的资源。因为提供了现有代码下面是所有资源的下载。
byte[] zipFileBytes = ((ScreenCaptureHtmlUnitDriver) driver).getScreenshotAs(OutputType.BYTES);
FileUtils.writeByteArrayToFile(new File("D:\\TEMP.PNG"), zipFileBytes);
最佳答案
错误表明代码正在尝试将 byte[]
转换为 File
。很容易理解为什么如果您只是从 getScreenshotAs
中删除未使用的路径:
public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
byte[] archive = new byte[0];
try {
archive = downloadCssAndImages(getWebClient(), (HtmlPage) getCurrentWindow().getEnclosedPage());
} catch (Exception e) {
}
return (X) archive;
}
您无法从中获取文件
。 OutputType.FILE
不受支持,因此您必须自己处理文件输出。幸运的是,这很容易。您可以将代码更改为:
byte[] zipFileBytes = ((ScreenCaptureHtmlUnitDriver) driver).getScreenshotAs(OutputType.BYTES);
FileUtils.writeByteArrayToFile(new File("D:\\TEMP.PNG"), zipFileBytes);
参见 FileUtils.writeByteArrayToFile () 更多。
关于java - 无法使用 HtmlUnitDriver [Selenium WebDriver java] 截屏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36254656/
我需要截屏并保存截屏。我需要在不使用与 PC 的任何连接或不取消手机根目录的情况下执行此操作。每当触发事件时,我都需要这样做。例如,当游戏中显示广告时......或者当游戏结束并显示蛇的分数等时。你能
我正在尝试捕捉(屏幕截图) View 。为此,我使用下面显示的一段代码将其作为 PNG 图像保存到我的文档目录中。 UIGraphicsBeginImageContextWithOptions(hig
本文实例总结了常见的java编程实现屏幕截图方法。分享给大家供大家参考,具体如下: 方法一: ?
你好,我是 Kagol,个人公众号:前端开源星球。 Fluent Editor 是一个基于 Quill 2.0 的富文本编辑器,在 Quill 基础上扩展了丰富的模块和格式,框架无关、 功能强大、开
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
我正在构建一个跨平台桌面应用程序。我正在使用 electronjs 框架开发我的桌面应用程序。我想在我的应用程序启动时添加每 5 分钟截取一次屏幕截图的功能! 帮助将不胜感激我的 main.js //
我从另一个包导入这个类并尝试调用这个方法,但它不起作用。 当我在同一个类中创建此方法并调用它时,它正在工作。 private void getScreenshot() throws IOExcept
我正在尝试截取增强现实屏幕的屏幕截图并将其作为位图传递给另一个 Activity 。 这是我用来截取屏幕截图的代码: 截屏功能 public static void tmpScreenshot(Bit
我有一个绘图区,我在里面画了一些图形或图像,所以我有这个回调来截屏: void CanvasToolBox::actionCanvasCamera() { auto root = Gdk::W
我正在使用 AVCaptureMetadataOutput 以使用 iOS QRCode、条形码扫描功能。这很好用,我得到了通过 AVCaptureMetadataOutput 委托(delegate
我想截取我 View 中特定部分的屏幕截图(具体来说是 ImageView ),是否有机会.... 最佳答案 看来您需要执行 renderInContext。 // Size of the resul
这个问题在这里已经有了答案: Read binary stdout data like screencap data from adb shell? (19 个回答) 关闭5年前. 我正在尝试尽快获取
嘿,我正在使用 WEBRTC 进行屏幕共享。但是我被困在我需要用户整个屏幕的地方,但是浏览器为用户提供了更多选项,例如应用程序和浏览器选项卡,所以我想检查用户从浏览器产生的弹出窗口中选择的选项,如果它
我正在压力测试中测试应用程序。 这就是为什么我需要它在发生错误(错误窗口打开)或挂起或崩溃时重新启动。同时,我需要收集有关导致重启的问题的所有有用信息:制作转储文件,并从错误窗口复制错误文本(和/或获
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
嗨,这里有人可以帮助我使用 phantomJS 截取我的 div 吗?我如何截取我的 #dropzone 然后将其附加到同一页面? 请帮忙。 最佳答案 有两种方法可以部分呈现网页。 1) 只用 div
这是我写的用于保存网页截图的简单python代码。 from selenium import webdriver import time driver=webdriver.Firefox() driv
出于安全原因,我当前正在构建的应用程序要求应用程序必须阻止操作系统在应用程序被插入后台时截取该应用程序的屏幕截图。这样在应用之间切换时将无法看到最后一个 Activity 屏幕。 我打算将此功能放在应
我正在尝试从 Silverlight 5 应用程序中截取子类 XNA DrawingSurface 元素的屏幕截图。这个 sl 应用程序将在一个 aspx 页面内运行。 这是我迄今为止尝试过但没有成功
我正在使用 Xcode 构建 iPhone/iPad 应用程序。 现在我想截取这个应用程序的屏幕截图。 尺寸为 960x640。 那怎么办? 模拟器屏幕太小 最佳答案 您可以使用 cmd+S进入模拟器
我是一名优秀的程序员,十分优秀!