使用Jsoup解析奥林巴斯相机页面返回null,求解决方案
问题分析与解决方案
以下是导致解析结果返回null的核心问题及对应修复方案:
1. 网络请求未使用传入的URL参数
你的HTMLParser.getHTML()方法硬编码了固定地址,完全忽略了传入的url参数,导致请求地址错误:
// 错误写法 Document doc = Jsoup.connect("oishare/DCIM/100OLYMP").get(); // 正确写法:使用传入的参数 Document doc = Jsoup.connect(url).get();
2. 主线程执行网络请求(Android 严格限制)
Android从API 11开始禁止在主线程执行同步网络请求,你直接在MainActivity.onCreate()里调用网络请求方法,会触发NetworkOnMainThreadException,捕获异常后返回null。
修复方案:用异步线程执行网络请求
修改HTMLParser为异步回调模式:
import android.os.Handler; import android.os.Looper; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class HTMLParser { public interface OnHtmlLoadedListener { void onSuccess(String html); void onError(Exception e); } public void getHTML(String url, OnHtmlLoadedListener listener) { new Thread(() -> { try { Document doc = Jsoup.connect(url).get(); // 切换回主线程更新UI new Handler(Looper.getMainLooper()).post(() -> listener.onSuccess(doc.html())); } catch (Exception e) { new Handler(Looper.getMainLooper()).post(() -> listener.onError(e)); } }).start(); } }
3. 未使用完整HTTP URL
你传入的oishare/DCIM/100OLYMP是相对路径,Jsoup无法识别,必须传入完整的相机Web服务URL:http://192.168.0.10/oishare/DCIM/100OLYMP。
4. 硬编码HTML片段替换不可靠
你之前用超长HTML字符串做替换的方式非常脆弱,页面结构稍有变化就会失效,改用Jsoup的DOM选择器操作更稳定。
完整MainActivity修复代码
package com.oly.rawshare; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.webkit.WebView; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class MainActivity extends AppCompatActivity { private WebView webView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webView.getSettings().setMediaPlaybackRequiresUserGesture(false); HTMLParser parser = new HTMLParser(); String targetUrl = "http://192.168.0.10/oishare/DCIM/100OLYMP"; parser.getHTML(targetUrl, new HTMLParser.OnHtmlLoadedListener() { @Override public void onSuccess(String html) { String processedHtml = processHtml(html); // 传入相机基础URL,保证相对资源能正常加载 webView.loadDataWithBaseURL("http://192.168.0.10", processedHtml, "text/html", "UTF-8", null); } @Override public void onError(Exception e) { e.printStackTrace(); // 此处可添加错误提示UI逻辑 } }); } // 用Jsoup处理HTML,替代硬编码字符串替换 private String processHtml(String html) { Document doc = Jsoup.parse(html); // 移除顶部导航栏相关元素 doc.select("div[style*=background-color: #2E2E2E]").remove(); doc.select("img[src=100OLYMP_files/title.gif]").remove(); doc.select("hr").remove(); // 批量替换目标链接 doc.select("a[href*=FILE.html?/DCIM/100OLYMP/]").forEach(element -> { String oldHref = element.attr("href"); String newHref = oldHref.replace("oishare/DCIM/100OLYMP/FILE.html?/DCIM/100OLYMP/", "oishare/DCIM/100OLYMP/"); element.attr("href", newHref); }); return doc.html(); } }
额外注意事项
- 确保在
AndroidManifest.xml中申请网络权限:
<uses-permission android:name="android.permission.INTERNET" />
内容的提问来源于stack exchange,提问作者laguro
相关产品推荐
相关产品推荐

