如何使用Selenium Java捕获开发者工具中指定API的响应数据
使用Selenium Java获取指定API响应数据的问题及修正方案
我想用Selenium Java获取开发者工具中某一指定API预览面板里的数据,但尝试后没成功,以下是我的代码:
public class CapAPIResponse { EdgeDriver driver; @Test public void seleniumTest() { driver = new EdgeDriver(); DevTools devTools = driver.getDevTools(); devTools.createSession(); devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); devTools.addListener(Network.requestWillBeSent(), requestConsumer ->{ Request request = requestConsumer.getRequest(); System.out.println(request.getUrl()); }); final RequestId[] requestId = new RequestId[1]; devTools.addListener(Network.responseReceived(), responseConsumer -> { Response response = responseConsumer.getResponse(); requestId[0] = responseConsumer.getRequestId(); if( response.getUrl().contains("ws_api.php?")) { System.out.println(response.getStatus() + " "+ response.getUrl()); Assert.assertEquals(response.getStatus() , 200); String responseBody = devTools.send(Network.getResponseBody(requestId[0] )).getBody(); System.err.println(responseBody); } }); driver.get("https://weatherstack.com/"); } }
问题分析
原代码存在几个核心问题导致获取不到响应数据:
responseReceived事件触发时,响应体可能还未完全加载完成,此时调用getResponseBody会返回空或抛出异常- 用数组存储
requestId存在线程安全风险,DevTools监听器是异步执行的,可能出现ID覆盖的情况 - 没有处理响应体为空的场景,容易出现空指针异常
修正后的代码
import org.junit.Assert; import org.junit.Test; import org.openqa.selenium.edge.EdgeDriver; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.v125.network.Network; import org.openqa.selenium.devtools.v125.network.model.RequestId; import java.util.Optional; public class CapAPIResponse { EdgeDriver driver; @Test public void seleniumTest() { driver = new EdgeDriver(); DevTools devTools = driver.getDevTools(); devTools.createSession(); // 启用Network监控,设置最大请求缓存数,避免丢失请求 devTools.send(Network.enable(Optional.of(1000000), Optional.empty(), Optional.empty())); // 监听请求加载完成事件,确保响应体已完全就绪 devTools.addListener(Network.loadingFinished(), loadingFinished -> { RequestId currentRequestId = loadingFinished.getRequestId(); // 获取请求对应的响应头,判断是否为目标API devTools.send(Network.getResponseHeaders(currentRequestId)).ifPresent(responseHeaders -> { String apiUrl = responseHeaders.getUrl(); if (apiUrl.contains("ws_api.php?")) { // 获取响应体,处理空值情况 devTools.send(Network.getResponseBody(currentRequestId)).ifPresent(responseBody -> { System.out.println("目标API状态码:" + responseHeaders.getStatus()); System.out.println("目标API地址:" + apiUrl); System.out.println("响应体内容:"); System.err.println(responseBody.getBody()); Assert.assertEquals(200, responseHeaders.getStatus()); }); } }); }); driver.get("https://weatherstack.com/"); // 等待页面加载完成并触发API请求,实际项目建议用显式等待替代Thread.sleep try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } driver.quit(); } }
关键修正说明
- 改用
loadingFinished事件:该事件在请求完全加载完成后触发,保证响应体已经可以被获取 - 避免共享变量风险:直接在回调中使用当前请求的
RequestId,不再用数组存储共享ID - 空值安全处理:使用
Optional的ifPresent方法,避免因响应头或响应体为空导致的空指针异常 - 添加等待逻辑:确保页面有足够时间加载并触发目标API请求,实际项目推荐用Selenium的显式等待(如等待页面某个元素加载完成)替代
Thread.sleep - 关闭驱动资源:测试结束后调用
driver.quit()释放浏览器资源
内容的提问来源于stack exchange,提问作者Delta
相关产品推荐
相关产品推荐

