我知道以前是不可能的,但是现在有了以下更新:
https://developers.google.com/web/updates/2017/04/devtools-release-
notes#screenshots
使用Chrome开发工具似乎可以做到这一点。
现在可以在Java中使用Selenium吗?
要使用Java中的Selenium Webdriver进行此工作需要花费一些工作。.正如Florent
B所暗示的那样,我们需要更改默认ChromeDriver的某些类使用才能使此项工作。首先,我们需要制作一个新的DriverCommandExecutor,以添加新的Chrome命令:
import com.google.common.collect.ImmutableMap;
import org.openqa.selenium.remote.CommandInfo;
import org.openqa.selenium.remote.http.HttpMethod;
import org.openqa.selenium.remote.service.DriverCommandExecutor;
import org.openqa.selenium.remote.service.DriverService;
public class MyChromeDriverCommandExecutor extends DriverCommandExecutor {
private static final ImmutableMap<String, CommandInfo> CHROME_COMMAND_NAME_TO_URL;
public MyChromeDriverCommandExecutor(DriverService service) {
super(service, CHROME_COMMAND_NAME_TO_URL);
}
static {
CHROME_COMMAND_NAME_TO_URL = ImmutableMap.of("launchApp", new CommandInfo("/session/:sessionId/chromium/launch_app", HttpMethod.POST)
, "sendCommandWithResult", new CommandInfo("/session/:sessionId/chromium/send_command_and_get_result", HttpMethod.POST)
);
}
}
之后,我们需要创建一个新的ChromeDriver类,然后将使用该类。我们需要创建类,因为原始类没有构造函数可让我们替换命令执行程序…因此,新类变为:
import com.google.common.collect.ImmutableMap;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.html5.LocalStorage;
import org.openqa.selenium.html5.Location;
import org.openqa.selenium.html5.LocationContext;
import org.openqa.selenium.html5.SessionStorage;
import org.openqa.selenium.html5.WebStorage;
import org.openqa.selenium.interactions.HasTouchScreen;
import org.openqa.selenium.interactions.TouchScreen;
import org.openqa.selenium.mobile.NetworkConnection;
import org.openqa.selenium.remote.FileDetector;
import org.openqa.selenium.remote.RemoteTouchScreen;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.html5.RemoteLocationContext;
import org.openqa.selenium.remote.html5.RemoteWebStorage;
import org.openqa.selenium.remote.mobile.RemoteNetworkConnection;
public class MyChromeDriver extends RemoteWebDriver implements LocationContext, WebStorage, HasTouchScreen, NetworkConnection {
private RemoteLocationContext locationContext;
private RemoteWebStorage webStorage;
private TouchScreen touchScreen;
private RemoteNetworkConnection networkConnection;
//public MyChromeDriver() {
// this(ChromeDriverService.createDefaultService(), new ChromeOptions());
//}
//
//public MyChromeDriver(ChromeDriverService service) {
// this(service, new ChromeOptions());
//}
public MyChromeDriver(Capabilities capabilities) {
this(ChromeDriverService.createDefaultService(), capabilities);
}
//public MyChromeDriver(ChromeOptions options) {
// this(ChromeDriverService.createDefaultService(), options);
//}
public MyChromeDriver(ChromeDriverService service, Capabilities capabilities) {
super(new MyChromeDriverCommandExecutor(service), capabilities);
this.locationContext = new RemoteLocationContext(this.getExecuteMethod());
this.webStorage = new RemoteWebStorage(this.getExecuteMethod());
this.touchScreen = new RemoteTouchScreen(this.getExecuteMethod());
this.networkConnection = new RemoteNetworkConnection(this.getExecuteMethod());
}
@Override
public void setFileDetector(FileDetector detector) {
throw new WebDriverException("Setting the file detector only works on remote webdriver instances obtained via RemoteWebDriver");
}
@Override
public LocalStorage getLocalStorage() {
return this.webStorage.getLocalStorage();
}
@Override
public SessionStorage getSessionStorage() {
return this.webStorage.getSessionStorage();
}
@Override
public Location location() {
return this.locationContext.location();
}
@Override
public void setLocation(Location location) {
this.locationContext.setLocation(location);
}
@Override
public TouchScreen getTouch() {
return this.touchScreen;
}
@Override
public ConnectionType getNetworkConnection() {
return this.networkConnection.getNetworkConnection();
}
@Override
public ConnectionType setNetworkConnection(ConnectionType type) {
return this.networkConnection.setNetworkConnection(type);
}
public void launchApp(String id) {
this.execute("launchApp", ImmutableMap.of("id", id));
}
}
这主要是原始类的副本,但是禁用了某些构造函数(因为某些所需的代码是程序包私有的)。如果需要这些构造函数,则必须将这些类放在org.openqa.selenium.chrome包中。
通过这些更改,您可以调用所需的代码,如Florent B.所示,但是现在可以使用Java使用Selenium API:
import com.google.common.collect.ImmutableMap;
import org.openqa.selenium.remote.Command;
import org.openqa.selenium.remote.Response;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class ChromeExtender {
@Nonnull
private MyChromeDriver m_wd;
public ChromeExtender(@Nonnull MyChromeDriver wd) {
m_wd = wd;
}
public void takeScreenshot(@Nonnull File output) throws Exception {
Object visibleSize = evaluate("({x:0,y:0,width:window.innerWidth,height:window.innerHeight})");
Long visibleW = jsonValue(visibleSize, "result.value.width", Long.class);
Long visibleH = jsonValue(visibleSize, "result.value.height", Long.class);
Object contentSize = send("Page.getLayoutMetrics", new HashMap<>());
Long cw = jsonValue(contentSize, "contentSize.width", Long.class);
Long ch = jsonValue(contentSize, "contentSize.height", Long.class);
/*
* In chrome 61, delivered one day after I wrote this comment, the method forceViewport was removed.
* I commented it out here with the if(false), and hopefully wrote a working alternative in the else 8-/
*/
if(false) {
send("Emulation.setVisibleSize", ImmutableMap.of("width", cw, "height", ch));
send("Emulation.forceViewport", ImmutableMap.of("x", Long.valueOf(0), "y", Long.valueOf(0), "scale", Long.valueOf(1)));
} else {
send("Emulation.setDeviceMetricsOverride",
ImmutableMap.of("width", cw, "height", ch, "deviceScaleFactor", Long.valueOf(1), "mobile", Boolean.FALSE, "fitWindow", Boolean.FALSE)
);
send("Emulation.setVisibleSize", ImmutableMap.of("width", cw, "height", ch));
}
Object value = send("Page.captureScreenshot", ImmutableMap.of("format", "png", "fromSurface", Boolean.TRUE));
// Since chrome 61 this call has disappeared too; it does not seem to be necessary anymore with the new code.
// send("Emulation.resetViewport", ImmutableMap.of());
send("Emulation.setVisibleSize", ImmutableMap.of("x", Long.valueOf(0), "y", Long.valueOf(0), "width", visibleW, "height", visibleH));
String image = jsonValue(value, "data", String.class);
byte[] bytes = Base64.getDecoder().decode(image);
try(FileOutputStream fos = new FileOutputStream(output)) {
fos.write(bytes);
}
}
@Nonnull
private Object evaluate(@Nonnull String script) throws IOException {
Map<String, Object> param = new HashMap<>();
param.put("returnByValue", Boolean.TRUE);
param.put("expression", script);
return send("Runtime.evaluate", param);
}
@Nonnull
private Object send(@Nonnull String cmd, @Nonnull Map<String, Object> params) throws IOException {
Map<String, Object> exe = ImmutableMap.of("cmd", cmd, "params", params);
Command xc = new Command(m_wd.getSessionId(), "sendCommandWithResult", exe);
Response response = m_wd.getCommandExecutor().execute(xc);
Object value = response.getValue();
if(response.getStatus() == null || response.getStatus().intValue() != 0) {
//System.out.println("resp: " + response);
throw new MyChromeDriverException("Command '" + cmd + "' failed: " + value);
}
if(null == value)
throw new MyChromeDriverException("Null response value to command '" + cmd + "'");
//System.out.println("resp: " + value);
return value;
}
@Nullable
static private <T> T jsonValue(@Nonnull Object map, @Nonnull String path, @Nonnull Class<T> type) {
String[] segs = path.split("\\.");
Object current = map;
for(String name: segs) {
Map<String, Object> cm = (Map<String, Object>) current;
Object o = cm.get(name);
if(null == o)
return null;
current = o;
}
return (T) current;
}
}
这使您可以使用指定的命令,并在其中创建带有png格式图像的文件。当然,您也可以通过在字节上使用ImageIO.read()直接创建BufferedImage。
问题内容: 我正在尝试使用WebdriverIO截取整个页面的屏幕截图。 我读过,最好的方法是使用WebdriverCSS增强我的WebdriverIO流。WebdriverCSS自动截图整个页面? 问题是WebdriverCSS对我不起作用。我认为是因为它尚未与兼容。 有什么办法可以使它起作用,或者可以使用其他解决方案? 我的代码: ( 这是生产什么,但在回调中未定义的值 ) !EDIT: 这是
在selenium web驱动程序中,我无法使用testng和maven将其显示在控制台中 JAVAlang.VerifyError:(类:junereleasemain/NewTest,方法:testFirstResult签名:()V)java函数的参数不兼容。朗,同学们。java上的getDeclaredMethods0(本机方法)。朗,同学们。java上的privateGetDeclared
可以使用SeleniumWebDriver拍摄屏幕截图。 它会截取网页的整个区域,但浏览器窗口(boarder)不包括在此截图中。 有没有一种方法来采取与Selenium网络驱动程序截图,以便整个浏览器窗口被捕获? 我想看到所有的状态栏,选项卡和按钮。 这是可能的。NET,但它有可能会屏蔽其他内容(例如,浏览器被最小化),所以我想使用selenium。
嗨,我如何在Windows电脑上使用任何浏览器拍摄网页的完整屏幕截图? 每当我用PrintScreen截图时,它只截图显示页面,但我希望截图的高度为整页。我们能拍完整的截图吗,包括隐藏的八张? 抱歉我英语不好。 我有firefox和chrome。
问题内容: 我想获得活动的“全页”屏幕截图。该视图包含一个RecyclerView,其中包含许多项。 我可以使用此功能拍摄当前视图的屏幕截图: 但是它仅包含我可以正常查看的项目(符合预期)。 截屏时,有什么方法可以使RecyclerView神奇地完整显示(一次显示所有项目)? 如果没有,我应该如何解决这个问题? 问题答案: 这是我的解决方案,当 所有项目的尺寸都相同 并且 只有一种类型的项目时 。
可在游戏中等拍摄并保存任何场景。同时按下PS键和START键。 可从(照片)查看已保存的信息。 若要拍摄画面截图,需事先将PS Vita专用存储卡插入主机。 因画面或应用程序的状态,可能无法拍摄画面截图。