如何在Java中通过WebView从指定类名的DOM元素获取数据
Android WebView:通过类名获取DOM元素并传递到Java层
前置准备
首先确保WebView开启JavaScript支持,并配置JS与Java的交互通道:
// 初始化WebView时的基础配置 WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); // 注入自定义Java接口供JS调用,"$$"是JS中调用的对象名 webView.addJavascriptInterface(new JsBridge(), "$$");
自定义JsBridge类,提供接收JS数据的方法(API 17+必须添加@JavascriptInterface注解):
public class JsBridge { @JavascriptInterface public void sendElementData(String elementJson) { // 解析并处理从JS传递的DOM元素数据 try { JSONArray elements = new JSONArray(elementJson); for (int i = 0; i < elements.length(); i++) { JSONObject elem = elements.getJSONObject(i); String text = elem.getString("text"); String html = elem.getString("html"); Log.d("WebView", "元素[" + i + "] 文本:" + text + ",HTML片段:" + html); } } catch (JSONException e) { Log.e("WebView", "DOM数据解析失败:" + e.getMessage()); } } // 保留原示例中的log方法(若业务需要) @JavascriptInterface public void log(String responseText, String url, String args) { // 原逻辑实现 } }
在onPageFinished中注入JS获取目标类名元素
在你提供的onPageFinished方法中,添加获取指定类名DOM元素的JS逻辑,提取数据后调用Java接口传递:
@Override public void onPageFinished(WebView view, String url) { setTitle(view.getTitle()); // 保留原有的注入代码 view.loadUrl("javascript:function injek3(){window.hasdir=1;window.dir=function(n){var r=[];for(var t in n)'function'==typeof n[t]&&r.push(t);return r}};if(window.hasdir!=1){injek3();}"); view.loadUrl("javascript:function injek2(){window.touchblock=0,window.dummy1=1,document.addEventListener('click',function(n){if(1==window.touchblock){n.preventDefault();n.stopPropagation();var t=document.elementFromPoint(n.clientX,n.clientY);window.ganti=function(n){t.outerHTML=n},window.gantiparent=function(n){t.parentElement.outerHTML=n},$$.print(t.parentElement.outerHTML, t.outerHTML)}},!0)}1!=window.dummy1&&injek2();"); view.loadUrl("javascript:function injek(){window.hasovrde=1;var e=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(ee,nn,aa){this.addEventListener('load',function(){$$.log(this.responseText, nn, JSON.stringify(arguments))}),e.apply(this,arguments)}};if(window.hasovrde!=1){injek();}"); // 新增:获取指定类名的DOM元素并传递到Java层 String targetClass = "your-target-class"; // 替换为实际要查找的类名 view.loadUrl("javascript:(function(){" + "var elems = document.getElementsByClassName('" + targetClass + "');" + "var data = [];" + "for(var i=0; i<elems.length; i++){" + "var elem = elems[i];" + // 按需提取数据,比如文本、HTML、属性等 "data.push({" + "text: elem.textContent.trim()," + "html: elem.outerHTML," + "className: elem.className" + "});" + "}" + // 调用Java接口,转成JSON字符串便于解析 "$$.sendElementData(JSON.stringify(data));" + "})()"); super.onPageFinished(view, url); }
更安全的替代方案(API 19+)
如果应用目标API为19及以上,推荐使用evaluateJavascript替代loadUrl,无需注入Java接口,安全性更高:
@Override public void onPageFinished(WebView view, String url) { // ... 保留原有逻辑 ... String targetClass = "your-target-class"; view.evaluateJavascript("(function(){" + "var elems = document.getElementsByClassName('" + targetClass + "');" + "var data = [];" + "for(var i=0; i<elems.length; i++){" + "data.push({text: elems[i].textContent.trim(), html: elems[i].outerHTML});" + "}" + "return JSON.stringify(data);" + "})()", new ValueCallback<String>() { @Override public void onReceiveValue(String result) { if (result != null) { try { JSONArray elements = new JSONArray(result); // 解析处理数据,逻辑同JsBridge中的方法 } catch (JSONException e) { e.printStackTrace(); } } } }); super.onPageFinished(view, url); }
关键注意点
- DOM加载时机:
onPageFinished是执行DOM操作的合适时机,但如果页面存在动态加载内容,可能需要添加延迟或监听DOM变化事件。 - 元素匹配:若仅需第一个匹配元素,可使用
document.querySelector('.target-class')替代getElementsByClassName。 - 安全风险:避免在
addJavascriptInterface的方法中暴露敏感操作,高版本系统优先使用evaluateJavascript。
内容的提问来源于stack exchange,提问作者sanju
相关产品推荐
相关产品推荐

