Android应用获取JavaScript动态加载Href链接的可行方案求助
Android端获取JS动态加载搜索结果的可行方案
方案1:利用WebView拦截搜索接口请求
WebView原生支持JS执行,你可以通过它模拟搜索操作,同时拦截后端的搜索API请求,直接拿到结构化数据,比解析页面DOM更高效:
- 配置WebView启用JS和DOM存储,确保能正常渲染页面
- 页面加载完成后,用
evaluateJavascript()执行JS代码,模拟输入关键词并触发搜索 - 重写
WebViewClient的shouldInterceptRequest()方法,识别搜索接口的请求,读取响应数据并解析链接
示例代码:
WebView webView = findViewById(R.id.webview); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); // 启用DOM存储,支持复杂JS页面 webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { String requestUrl = request.getUrl().toString(); // 替换为目标网站的搜索接口特征,比如包含"/search/api" if (requestUrl.contains("/search/api")) { try { URLConnection conn = new URL(requestUrl).openConnection(); // 模拟WebView的请求头,避免被拦截 conn.setRequestProperty("User-Agent", view.getSettings().getUserAgentString()); InputStream inputStream = conn.getInputStream(); // 读取响应内容,解析JSON获取链接 String response = new BufferedReader(new InputStreamReader(inputStream)) .lines().collect(Collectors.joining()); // 这里解析response提取所需链接,比如用Gson/JSONObject // 处理完成后可返回null,终止WebView继续加载该请求 return new WebResourceResponse("application/json", "utf-8", inputStream); } catch (IOException e) { e.printStackTrace(); } } return super.shouldInterceptRequest(view, request); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 替换为目标网站搜索框和按钮的ID/选择器 String searchJs = "document.querySelector('#search-input').value='你的关键词';" + "document.querySelector('#search-btn').click();"; view.evaluateJavascript(searchJs, null); } }); webView.loadUrl("目标网站的搜索页面URL");
方案2:抓包分析搜索API,直接调用后端接口
大部分网站的搜索功能都是通过AJAX请求后端API实现的,直接调用API比用WebView更轻量:
- 用抓包工具捕获搜索时的网络请求,找到对应的API接口地址
- 复制请求头(User-Agent、Cookie、Referer等),确保和浏览器请求一致,避免被反爬
- 用OkHttp/Retrofit直接发起请求,解析返回的JSON数据获取链接
示例代码(OkHttp):
OkHttpClient client = new OkHttpClient.Builder() .cookieJar(new CookieJar() { // 可存储抓包获取的Cookie,维持会话 private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>(); @Override public void saveFromResponse(HttpUrl url, List<Cookie> cookies) { cookieStore.put(url.host(), cookies); } @Override public List<Cookie> loadForRequest(HttpUrl url) { List<Cookie> cookies = cookieStore.get(url.host()); return cookies != null ? cookies : new ArrayList<>(); } }) .build(); Request request = new Request.Builder() .url("搜索API地址?keyword=你的关键词") .addHeader("User-Agent", "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36") .addHeader("Referer", "目标网站搜索页面URL") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String respBody = response.body().string(); // 用Gson或JSONObject解析respBody,提取链接列表 } } });
方案3:调整HTMLUnit配置重新尝试
之前HTMLUnit失败大概率是配置问题,调整以下设置即可模拟Chrome浏览器执行JS:
WebClient webClient = new WebClient(BrowserVersion.CHROME); webClient.getOptions().setJavaScriptEnabled(true); webClient.getOptions().setCssEnabled(false); // 禁用CSS加快加载 webClient.getOptions().setThrowExceptionOnScriptError(false); // 忽略JS错误,避免中断 webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); // 加载搜索页面 HtmlPage page = webClient.getPage("目标网站搜索页面URL"); // 找到搜索框和按钮(替换为对应选择器) HtmlInput searchInput = page.querySelector("#search-input"); HtmlElement searchBtn = page.querySelector("#search-btn"); searchInput.setValueAttribute("你的关键词"); searchBtn.click(); // 等待JS异步加载完成(根据页面情况调整时长) webClient.waitForBackgroundJavaScript(5000); // 提取链接(替换为目标链接的选择器) List<HtmlAnchor> resultLinks = page.querySelectorAll("a.result-item-link"); for (HtmlAnchor anchor : resultLinks) { String link = anchor.getHrefAttribute(); // 处理链接 } webClient.close();
内容的提问来源于stack exchange,提问作者KEYS
相关产品推荐
相关产品推荐

