这是一个非常常见的需求,通常用于调试、数据分析或实现特定功能,核心思路是利用 WebView 提供的回调接口,在网页加载完成后获取其内容。

android webview 网页源码
(图片来源网络,侵删)

核心方法:WebViewClientonPageFinished 回调

当 WebView 完成加载一个页面后,系统会调用 WebViewClientonPageFinished(WebView view, String url) 方法,我们就是在这个方法里,通过 view 对象来获取当前的 HTML 源码。

最关键的方法是:view.getUrl()view.getPageSource()

  • getUrl(): 获取当前 WebView 加载的 URL 地址。
  • getPageSource(): 获取当前页面的完整 HTML 源码,这是实现目标的核心方法。

完整代码示例

下面是一个完整的、可以直接运行的 Activity 示例,它展示如何加载一个网页,并在加载完成后将其源码打印到 Logcat 中,同时显示在一个 TextView 里。

布局文件 (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">
    <WebView
        android:id="@+id/my_webview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
    <TextView
        android:id="@+id/source_code_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#f0f0f0"
        android:text="网页源码将显示在这里..."
        android:textIsSelectable="true" />
</LinearLayout>

Java 代码 (MainActivity.java)

package com.example.webviewdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "WebViewSourceCode";
    private WebView webView;
    private TextView sourceCodeTextView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化控件
        webView = findViewById(R.id.my_webview);
        sourceCodeTextView = findViewById(R.id.source_code_text);
        // 1. 启用 JavaScript (如果网页需要)
        webView.getSettings().setJavaScriptEnabled(true);
        // 2. 设置 WebViewClient,这是获取源码的关键
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                // 网页加载完成后,此方法会被调用
                Log.d(TAG, "页面加载完成,URL: " + url);
                // 3. 获取网页源码
                String htmlSource = view.getPageSource();
                // 4. 将源码打印到 Logcat
                Log.d(TAG, "网页源码:\n" + htmlSource);
                // 5. 将源码显示在 TextView 中 (注意:源码可能很长,建议只显示部分或用其他方式查看)
                // 为了避免UI卡顿,可以考虑使用异步任务或只显示前N个字符
                sourceCodeTextView.setText(htmlSource.length() > 5000 ?
                        htmlSource.substring(0, 5000) + "\n\n... (源码过长,已截断)" :
                        htmlSource);
            }
        });
        // 6. 加载一个网页
        // 加载本地 HTML 文件
        // webView.loadUrl("file:///android_asset/my_page.html");
        // 加载网络 URL
        webView.loadUrl("https://www.baidu.com");
    }
    // 7. 处理返回键,让 WebView 能够返回上一页而不是退出应用
    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

AndroidManifest.xml 配置

别忘了在 AndroidManifest.xml 中添加网络权限和声明 WebView 所需的 usesCleartextTraffic(如果加载的是 HTTP 网站或某些 HTTPS 网站)。

android webview 网页源码
(图片来源网络,侵删)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.webviewdemo">
    <!-- 添加网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:usesCleartextTraffic="true"  <!-- 允许 HTTP 请求,对某些 HTTPS 网站也必要 -->
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.WebViewDemo">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

关键点解析与注意事项

  1. onPageFinished 的时机

    • 这个方法在页面及其所有资源(如图片、CSS、JS)都加载完毕后才会调用。
    • 如果网页有大量异步加载的内容(例如通过 AJAX 动态加载),onPageFinished 只会在初始 HTML 加载完成后触发,此时获取的源码可能不包含这些动态加载的内容,如果需要获取最终渲染后的完整 DOM,情况会更复杂,可能需要与前端 JS 交互。
  2. 性能考虑

    • 网页源码可能非常巨大(特别是现代网站),直接将其全部加载到内存并显示在 TextView 中可能会导致内存问题或 UI 卡顿。
    • 建议:在实际应用中,不要直接将整个源码显示在 UI 上,可以:
      • 只打印到 Logcat 进行调试。
      • 只截取源码的前几百个字符进行预览。
      • 将源码保存到文件中。
      • 使用 StringBuilder 或流式处理来分析源码,而不是一次性全部读入。
  3. JavaScript 与动态内容

    • 如上所述,getPageSource() 获取的是服务器返回的原始 HTML,而不是浏览器渲染后的 DOM。
    • 如果网页内容是通过 JavaScript 动态生成的(使用 React, Vue, Angular 框架),onPageFinished 触发时这些内容可能还未添加到 DOM 中。
    • 如何获取动态内容?
      • 与 JS 交互,在 onPageFinished 中,通过 WebView.evaluateJavascript() 执行一段 JS 代码,让 JS 将整个 document.documentElement.outerHTML (渲染后的完整 HTML) 返回给 Java 代码。
        // 在 onPageFinished 中添加
        webView.evaluateJavascript("(function() { return document.documentElement.outerHTML; })();", value -> {
            // value 是 JS 返回的结果,是一个 String 类型
            Log.d(TAG, "通过 JS 获取的渲染后源码: " + value);
            // 在这里处理 value
        });
      • 等待,可以设置一个定时器,延迟几秒后再调用 getPageSource(),给 JS 脚本留出执行时间,但这非常不可靠,不推荐。
  4. HTTPS 与安全

    • 在 Android 9 (API 28) 及以上,默认禁止使用 HTTP,如果你的目标网页是 http:// 开头的,需要在 AndroidManifest.xml<application> 标签中设置 android:usesCleartextTraffic="true"
    • 如果是 https://,但网站证书不受信任(例如自签名证书),WebView 可能会加载失败,需要处理 onReceivedSslError 回调来接受证书。

获取 Android WebView 网页源码的标准流程是:

  1. WebView 设置一个自定义的 WebViewClient
  2. 重写 onPageFinished(WebView view, String url) 方法。
  3. 在该方法内部,调用 view.getPageSource() 获取 HTML 字符串。
  4. 根据需求处理这个字符串(打印、保存、分析等)。

对于静态网页,这是最直接、最可靠的方法,对于动态网页,则需要结合 JavaScript 交互来获取最终渲染的源码。