如何在CI环境中结合RemoteWebDriver使用Selenium 4 NetworkInterceptor?
在CI环境中结合RemoteWebDriver使用Selenium 4 NetworkInterceptor的可行方案
针对你遇到的RemoteWebDriver未实现HasDevTools接口导致NetworkInterceptor无法初始化的问题,以下是三种可行解决方案:
方案1:使用浏览器专属的远程驱动实例
Selenium 4为Chrome等浏览器提供了支持远程连接的构造方法,创建的实例既具备远程连接Selenium Hub的能力,又实现了HasDevTools接口,可直接使用NetworkInterceptor。
代码示例
import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.devtools.NetworkInterceptor; import org.openqa.selenium.devtools.Filter; import java.net.URL; public class RemoteNetworkInterceptorExample { public static void main(String[] args) throws Exception { URL seleniumHubUrl = new URL("http://your-hub-address:4444/wd/hub"); // 配置Chrome选项,适配CI环境(如无头模式) ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new", "--no-sandbox", "--disable-dev-shm-usage"); // 创建Chrome远程驱动实例,该实例实现HasDevTools接口 RemoteWebDriver driver = new RemoteWebDriver(seleniumHubUrl, options); // 初始化NetworkInterceptor并使用 try (NetworkInterceptor interceptor = new NetworkInterceptor( driver, (Filter) next -> request -> { // 自定义请求拦截逻辑,比如修改请求头 request.addHeader("X-Custom-Header", "ci-test"); return next.apply(request); })) { driver.get("https://example.com"); // 执行测试操作 } finally { driver.quit(); } } }
方案2:手动绑定DevTools到通用RemoteWebDriver
若必须使用通用RemoteWebDriver,可手动获取DevTools会话地址并建立连接,绕开接口实现限制。需注意CI环境中的Selenium Node需配置Chrome开启远程调试端口。
代码示例
import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.v120.network.Network; import java.net.URL; import java.util.Optional; public class ManualDevToolsBinding { public static void main(String[] args) throws Exception { URL seleniumHubUrl = new URL("http://your-hub-address:4444/wd/hub"); ChromeOptions options = new ChromeOptions(); // 强制开启远程调试端口,需确保Node机器的9222端口可被Hub访问 options.addArguments("--remote-debugging-port=9222"); RemoteWebDriver driver = new RemoteWebDriver(seleniumHubUrl, options); // 从Capabilities中提取DevTools会话地址(需根据实际Capabilities结构解析) String chromeOptions = driver.getCapabilities().getCapability("goog:chromeOptions").toString(); // 示例解析逻辑,实际需根据返回值调整 String devToolsWsUrl = "ws://your-node-ip:9222/devtools/browser/" + chromeOptions.split("browserId\":\"")[1].split("\"")[0]; // 手动创建并连接DevTools DevTools devTools = new DevTools(); devTools.connect(new URL(devToolsWsUrl)); devTools.createSession(); // 启用Network域并设置拦截规则 devTools.getDomains().network().enable(Optional.empty(), Optional.empty(), Optional.empty()); devTools.getDomains().network().beforeRequestSent(request -> { if (request.getRequestUrl().contains("/api/")) { // 自定义请求修改逻辑 System.out.println("Intercepted request: " + request.getRequestUrl()); } }); // 执行测试 driver.get("https://example.com"); // 清理资源 devTools.disconnect(); driver.quit(); } }
方案3:使用第三方代理工具拦截请求
若DevTools相关方案受限于环境配置,可采用BrowserMob Proxy等第三方工具实现请求响应拦截,无需依赖Selenium的DevTools能力。
代码示例
import org.openqa.selenium.Proxy; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.chrome.ChromeOptions; import net.lightbody.bmp.BrowserMobProxy; import net.lightbody.bmp.BrowserMobProxyServer; import net.lightbody.bmp.client.ClientUtil; import net.lightbody.bmp.filters.RequestFilter; import net.lightbody.bmp.filters.ResponseFilter; import net.lightbody.bmp.util.HttpMessageContents; import net.lightbody.bmp.util.HttpMessageInfo; import java.net.URL; public class ProxyInterceptorExample { public static void main(String[] args) throws Exception { // 启动BrowserMob Proxy服务 BrowserMobProxy proxy = new BrowserMobProxyServer(); proxy.start(0); int proxyPort = proxy.getPort(); // 配置Chrome使用该代理 Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy); ChromeOptions options = new ChromeOptions(); options.setProxy(seleniumProxy); // 连接Selenium Hub URL seleniumHubUrl = new URL("http://your-hub-address:4444/wd/hub"); RemoteWebDriver driver = new RemoteWebDriver(seleniumHubUrl, options); // 添加请求拦截规则 proxy.addRequestFilter((RequestFilter) (request, contents, messageInfo) -> { if (request.getUri().contains("/target-api/")) { // 修改请求体 contents.setTextContents("modified-request-body"); } return null; }); // 添加响应拦截规则 proxy.addResponseFilter((ResponseFilter) (response, contents, messageInfo) -> { if (response.getStatus().getStatusCode() == 200) { // 修改响应内容 contents.setTextContents("{\"status\":\"success\",\"data\":\"modified\"}"); } }); // 执行测试 driver.get("https://example.com"); // 清理资源 driver.quit(); proxy.stop(); } }
内容的提问来源于stack exchange,提问作者Martin Janíček
相关产品推荐
相关产品推荐

