Java+Selenium自动化测试:如何从非DOM图表获取JSON变量并存入Java变量
解决Selenium提取图表数值(DOM中无显示)的问题
我之前做Web自动化测试时也碰到过一模一样的情况——图表渲染出来的数值根本不在DOM节点里,常规的findElement完全拿不到数据。结合你给出的HTML片段(里面有data-bind="bqVisualization: {type:style, data: statistics}"),大概率是用了Knockout这类MVVM框架绑定数据,图表是基于前端ViewModel里的statistics数据渲染的,而非直接把数值写到DOM中。下面给你几个靠谱的解决方案:
方案1:直接从前端ViewModel提取数据
既然数据绑定在statistics变量里,我们可以通过Selenium执行JavaScript脚本,直接获取这个ViewModel里的数据:
- 如果
statistics是全局变量:JavascriptExecutor js = (JavascriptExecutor) driver; Object statisticsData = js.executeScript("return window.statistics;"); // 把返回的Object转成对应的Java对象(比如用Jackson/Gson解析) - 如果是Knockout的绑定上下文:
你的HTML里有data-bind属性,大概率是Knockout框架,那可以获取元素的绑定上下文来拿到数据:JavascriptExecutor js = (JavascriptExecutor) driver; Object chartData = js.executeScript(""" var chartElement = document.querySelector('div[data-bind*="bqVisualization"]'); var viewModel = ko.dataFor(chartElement); return viewModel.statistics(); """); // 解析chartData得到需要的数值
方案2:拦截接口请求获取原始数据
图表的数据一般都是通过后端接口返回的,我们可以用Chrome DevTools Protocol来监听并获取接口响应:
// 初始化DevTools ChromeDriver driver = new ChromeDriver(); DevTools devTools = driver.getDevTools(); devTools.createSession(); // 启用网络监听 devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); // 监听响应事件 devTools.addListener(Network.responseReceived(), response -> { String url = response.getResponse().getUrl(); // 匹配图表数据对应的接口URL if (url.contains("/api/statistics")) { // 获取响应体 String responseBody = devTools.send(Network.getResponseBody(response.getRequestId())).getBody(); // 用JSON解析库(比如Jackson)解析responseBody,提取需要的数值 System.out.println("接口返回的数据:" + responseBody); } }); // 访问目标页面 driver.get("你的目标页面URL");
如果不想用DevTools,也可以直接用Java的HTTP客户端(比如OkHttp)调用该接口,前提是你能拿到接口的请求参数、鉴权信息(比如Cookie、Token)。
方案3:OCR图像识别(备选方案)
如果前两种方法都走不通,只能退而求其次用图像识别,但这种方法可靠性低,容易受图表样式、分辨率影响:
- 先截取图表区域的截图:
WebElement chartDiv = driver.findElement(By.cssSelector("div[data-bind*='bqVisualization']")); File chartScreenshot = chartDiv.getScreenshotAs(OutputType.FILE); - 用Tesseract OCR工具处理截图,提取文字数值。你需要引入Tesseract的Java依赖(比如
net.sourceforge.tess4j:tess4j),然后编写识别代码。
总结:优先用方案1或方案2,这两种方法获取的数据精准可靠;方案3只适合应急,不推荐作为长期解决方案。
内容的提问来源于stack exchange,提问作者K2017
相关产品推荐
相关产品推荐

