1. 概述
在 Web 開發中,動態從 API 使用 JavaScript 獲取網頁數據並不罕見。有時,我們可能希望捕獲這些 API 返回的 JavaScript 對象表示法 (JSON) 響應,以自動化數據提取、驗證數據或執行測試。對於此類任務,我們可以使用像 Selenium WebDriver 這樣的工具來捕獲 JSON 響應。但是,這並不總是簡單直接的。
在本教程中,我們將使用一種簡單而實用的方法來使用 Selenium 獲取 JSON 響應。
2. 基本和前提條件
Selenium 旨在用於瀏覽器自動化,通常與按鈕、輸入字段和鏈接等元素進行交互。 但是,它不直接提供用於捕獲原始網絡響應的 API。
為了演示一個解決方法,我們可以使用 Selenium 執行一系列任務:
- 加載頁面
- 等待 JSON 在頁面上顯示
- 使用驅動程序提取內容
為了説明,這種方法適用於頁面渲染後通過 fetch 或 XHR 返回的 JSON。
在繼續之前,我們需要確保已安裝以下前提條件:
- Java 11 或更高版本
- Maven
- Chrome 瀏覽器
- 與 Chrome 版本匹配的 ChromeDriver
現在,讓我們開始構建一個簡單的 HTML 頁面,該頁面可以從 JSON 對象中獲取內容,以便我們可以使用 Java Selenium 捕獲 JSON。
3. 項目設置
對於本項目,我們使用 Maven 來管理依賴項。
首先,讓我們創建一個 Maven 項目結構 selenium-json-demo。
$ mvn archetype:generate -DgroupId=com.example -DartifactId=selenium-json-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
[INFO] Scanning for projects...
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.150 s
[INFO] Finished at: 2025-09-02T08:01:51+03:00
[INFO] ------------------------------------------------------------------------一旦上述命令成功創建 Maven 項目結構,請導航到該項目:
$ cd selenium-json-demo在項目目錄下,我們適當地更新 pom.xml文件:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>selenium-json-demo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>selenium-json-demo</name>
<url>http://maven.apache.org</url>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- Selenium WebDriver -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.25.0</version>
</dependency>
<!-- JUnit for testing (optional) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<mainClass>com.example.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>pom.xml 文件設置了 Java 11 編譯器、Selenium WebDriver 依賴項和 Maven exec 插件,用於運行主類。 在這種配置下,<dependency> 標籤會拉取 Selenium 庫,用於驅動瀏覽器,以及 JUnit,如果我們要稍後實現測試用例。 同時,<build> 部分添加了 exec-maven-plugin,使我們能夠使用 mvn exec:java 運行主類 (com.example.App)。 如果沒有這個插件,Maven 不知道如何直接從命令行啓動 Selenium 代碼。
4. 編寫 HTML 測試頁面
在項目目錄下,讓我們創建一個簡單的 HTML 頁面 test.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test JSON Fetch</title>
</head>
<body>
<h1>Testing JSON Fetch</h1>
<pre id="output"></pre>
<script>
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(data => {
document.getElementById('output').textContent = JSON.stringify(data, null, 2);
})
.catch(error => console.error('Error fetching JSON:', error));
</script>
</body>
</html>那麼,我們來分解一下:
fetch:從 https://jsonplaceholder.typicode.com/todos/1 獲取 JSONdocument.getElementById('output').textContent:渲染 JSON<pre>:一個標籤,用於保留格式,以便於閲讀
通過本地提供此文件,我們模擬了 JSON 動態獲取並渲染在頁面上的確切場景。 <pre> 標籤保持格式不變,因此 Selenium 可以一次性捕獲整個 JSON 字符串。 這種方法反映了真實世界中儀表板或開發端點以純文本形式暴露 JSON 響應的情況。
5. 編寫 Java Selenium 代碼
現在,讓我們更新 <em src/main/java/com/example</em> 目錄下的 <em App.java</em> 文件:
package com.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class App {
public static void main(String[] args) {
// Optional: Set ChromeDriver path if not in system PATH
// System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();
try {
// Open local test page
driver.get("http://localhost:8000/test.html");
// Wait briefly for JSON to load
Thread.sleep(2000); // 2 seconds
// Capture JSON from <pre> element
String json = driver.findElement(By.id("output")).getText();
System.out.println("Captured JSON:\n" + json);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
driver.quit();
}
}
}讓我們分析上面的代碼:
WebDriver driver = new ChromeDriver():啓動 Chromedriver.get(“http://localhost:8000/test.html”):打開頁面Thread.sleep(2000):等待 JSON 加載driver.findElement(By.id(“output”)).getText():提取 JSON 文本
在此之後,我們應該能夠運行該項目。
6. 運行項目
當然,我們需要通過 HTTP 讓 ChromeDriver 加載 HTML 文件。
從項目目錄中,讓我們啓動一個本地服務器來運行 test.html:
$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...我們上面使用了 Python 內置的 HTTP 服務器。 任何簡單的靜態服務器都有效,因為關鍵在於 ChromeDriver 只能通過 http:// 或 https:// 方式加載文件,不能直接從文件系統加載,即使用 file:// 協議。
在本地服務器配置完成後,讓我們編譯項目:
$ mvn clean compile
[INFO] Scanning for projects...
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.752 s
[INFO] Finished at: 2025-09-02T10:32:19+03:00
[INFO] ------------------------------------------------------------------------在編譯項目後,我們可以運行 Selenium 程序:
$ mvn exec:java
[INFO] Scanning for projects...
...
Captured JSON:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 44.448 s
[INFO] Finished at: 2025-09-02T10:38:15+03:00
[INFO] ------------------------------------------------------------------------在輸出中,經常會遇到 CDP 版本警告:
WARNING: Unable to find version of CDP to use for 139.0.7258.66. You may need to include a dependency on a specific version of the CDP using something similar to `org.seleniumhq.selenium:selenium-devtools-v86:4.25.0` where the version ("v86") matches the version of the chromium-based browser you're using and the version number of the artifact is the same as Selenium's.在這種情況下,任何 CDP 版本警告都無害。
[WARNING] thread Thread[UrlChecker-2,5,com.example.App] was interrupted but is still alive after waiting at least 14994msecs此外,我們還可能遇到線程警告:
[WARNING] thread Thread[UrlChecker-2,5,com.example.App] was interrupted but is still alive after waiting at least 14994msecs由於 Maven 嘗試終止 Selenium 創建的線程,因此它們會發生。
7. 理解輸出
我們捕獲的JSON與fetch API返回並渲染在頁面上的內容完全一致。
為了説明,以下是其工作原理:
- Selenium 與瀏覽器交互
- JSON 在 DOM 中渲染,具體是 <pre> 元素
- Selenium 提取文本內容,因此我們獲得完整的 JSON 響應
因此,只要頁面渲染 JSON,該方法在不同瀏覽器中均有效,無需使用複雜的代理,這使得初學者易於實施。
相反,該方法的侷限性在於它僅適用於頁面渲染的 JSON。 此外,它不適用於沒有更新 DOM 的後台 API 調用。 如果我們需要攔截從未出現在 DOM 中的原始 API 響應,則需要使用像 Selenium DevTools 這樣的高級工具或像 BrowserMob 這樣的代理。
8. 結論
在本文中,我們探討了如何使用 Selenium 從 HTML 頁面獲取基本 JSON 響應。
通過利用頁面渲染 API 響應的方式,我們可以使用 Selenium WebDriver 加載頁面,等待響應,並將 JSON 直接從 DOM 中提取。在本例中,我們能夠從提供靜態 test.html 文件並使用 Selenium WebDriver 查找和提取 <pre> 標籤內的文本中獲取並打印 JSON。
現在,我們已經擁有一個最小的 Java Selenium 項目,該項目能夠從網頁中捕獲 JSON。