强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Chromium / ChromeDriver 完全指南 / 03 - Selenium 集成

03 - Selenium 集成

使用 Selenium WebDriver 控制 Chrome/Chromium,理解 WebDriver 协议工作原理,掌握浏览器启动与选项配置。


3.1 Selenium 简介

Selenium 是最成熟的浏览器自动化框架,始于 2004 年,目前由 W3C 标准化为 WebDriver 协议

Selenium 版本演进

版本年份关键变化
Selenium 1 (RC)2004通过 JS 注入控制浏览器,需启动 Selenium Server
Selenium 2 (WebDriver)2011引入 WebDriver API,直接控制浏览器
Selenium 32016独立 ChromeDriver,JSON Wire Protocol
Selenium 42021W3C WebDriver 协议标准化,新 API,BiDi 支持
Selenium 4.x (持续更新)2023+CDP 集成,相对定位器,更好的 DevTools 支持

架构总览

┌──────────────────────────────────────────────────────────┐
│                     测试脚本 (Python/Java/etc.)           │
├──────────────────────────────────────────────────────────┤
│                   Selenium Client Library                 │
│    (selenium-python / selenium-java / selenium-dotnet)   │
├──────────────────────────────────────────────────────────┤
│                  W3C WebDriver 协议                       │
│              (HTTP/JSON Wire Protocol)                    │
├────────────────────┬─────────────────────────────────────┤
│   ChromeDriver     │    geckodriver  │  msedgedriver     │
│   (Chrome/Chromium)│    (Firefox)    │  (Edge)           │
├────────────────────┴─────────────────────────────────────┤
│                   Chrome / Chromium                       │
└──────────────────────────────────────────────────────────┘

3.2 安装 Selenium

Python

pip install selenium

# 验证安装
python -c "import selenium; print(selenium.__version__)"

Java (Maven)

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.16.1</version>
</dependency>

Node.js

npm install selenium-webdriver

C# (.NET)

dotnet add package Selenium.WebDriver

3.3 第一个自动化脚本

Python

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

# 方式 1: 使用系统 PATH 中的 ChromeDriver
driver = webdriver.Chrome()

# 方式 2: 指定 ChromeDriver 路径
# service = Service('/usr/local/bin/chromedriver')
# driver = webdriver.Chrome(service=service)

# 打开页面
driver.get("https://www.google.com")

# 获取页面信息
print(f"标题: {driver.title}")
print(f"URL:  {driver.current_url}")

# 找到搜索框并输入
search_box = driver.find_element(By.NAME, "q")
search_box.send_keys("Selenium WebDriver")
search_box.submit()

time.sleep(2)
print(f"搜索后标题: {driver.title}")

# 关闭浏览器
driver.quit()

Java

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.By;

public class FirstScript {
    public static void main(String[] args) {
        // 创建 Chrome 驱动
        WebDriver driver = new ChromeDriver();

        try {
            // 打开页面
            driver.get("https://www.google.com");
            System.out.println("标题: " + driver.getTitle());

            // 搜索
            driver.findElement(By.name("q")).sendKeys("Selenium WebDriver");
            driver.findElement(By.name("q")).submit();

            Thread.sleep(2000);
            System.out.println("搜索后标题: " + driver.getTitle());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            driver.quit();
        }
    }
}

Node.js

const { Builder, By, Key, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

async function main() {
  // 创建驱动
  let driver = await new Builder()
    .forBrowser('chrome')
    .setChromeOptions(new chrome.Options())
    .build();

  try {
    await driver.get('https://www.google.com');
    console.log('标题:', await driver.getTitle());

    // 搜索
    await driver.findElement(By.name('q')).sendKeys('Selenium WebDriver', Key.RETURN);
    await driver.wait(until.titleContains('Selenium'), 5000);
    console.log('搜索后标题:', await driver.getTitle());
  } finally {
    await driver.quit();
  }
}

main();

3.4 WebDriver 协议详解

请求与响应格式

WebDriver 协议基于 HTTP RESTful API,所有通信均为 JSON 格式。

创建会话请求:

POST /session HTTP/1.1
Content-Type: application/json

{
  "capabilities": {
    "alwaysMatch": {
      "browserName": "chrome",
      "goog:chromeOptions": {
        "args": ["--headless", "--no-sandbox"]
      }
    }
  }
}

会话响应:

{
  "value": {
    "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "capabilities": {
      "browserName": "chrome",
      "browserVersion": "120.0.6099.71",
      "platformName": "linux",
      "goog:chromeOptions": { "debuggerAddress": "127.0.0.1:9222" }
    }
  }
}

常用 WebDriver 命令

HTTP 方法路径说明Selenium 方法
POST/session创建会话webdriver.Chrome()
DELETE/session/{id}关闭会话driver.quit()
POST/session/{id}/url导航到 URLdriver.get(url)
GET/session/{id}/url获取当前 URLdriver.current_url
GET/session/{id}/title获取页面标题driver.title
POST/session/{id}/element查找元素driver.find_element()
POST/session/{id}/element/{eid}/click点击元素element.click()
POST/session/{id}/element/{eid}/value输入文本element.send_keys()
POST/session/{id}/execute/sync执行 JSdriver.execute_script()
POST/session/{id}/screenshot截图driver.get_screenshot_as_png()

3.5 浏览器选项配置 (ChromeOptions)

ChromeOptions 是配置 Chrome 启动行为的核心类。

Python — 完整配置示例

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

options = Options()

# === 基础选项 ===
options.binary_location = "/usr/bin/google-chrome"  # Chrome 二进制路径
options.add_argument("--headless=new")              # 无头模式 (新)
options.add_argument("--no-sandbox")                # 禁用沙箱 (root 用户必须)
options.add_argument("--disable-dev-shm-usage")     # 使用 /tmp 替代 /dev/shm
options.add_argument("--disable-gpu")               # 禁用 GPU 加速

# === 窗口与显示 ===
options.add_argument("--window-size=1920,1080")     # 窗口大小
options.add_argument("--start-maximized")           # 最大化启动
options.add_argument("--force-device-scale-factor=1")  # 缩放比例

# === 网络 ===
options.add_argument("--proxy-server=http://proxy:8080")  # 代理
options.add_argument("--ignore-certificate-errors")        # 忽略证书错误
options.add_argument("--disable-extensions")               # 禁用扩展

# === 性能 ===
options.add_argument("--disable-logging")           # 禁用日志
options.add_argument("--disable-background-networking")  # 禁用后台网络
options.page_load_strategy = 'eager'                # 页面加载策略

# === 实验性选项 ===
options.add_experimental_option("prefs", {
    "download.default_directory": "/tmp/downloads",
    "download.prompt_for_download": False,
    "profile.default_content_setting_values.notifications": 2,  # 禁用通知
})

# === 附加扩展 ===
options.add_extension("/path/to/extension.crx")

# 创建驱动
driver = webdriver.Chrome(options=options)

Java — 配置示例

ChromeOptions options = new ChromeOptions();

// 基础选项
options.setBinary("/usr/bin/google-chrome");
options.addArguments("--headless=new");
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");
options.addArguments("--window-size=1920,1080");

// 性能选项
options.addArguments("--disable-extensions");
options.addArguments("--disable-gpu");

// 页面加载策略
options.setPageLoadStrategy(PageLoadStrategy.EAGER);

// 实验性选项
Map<String, Object> prefs = new HashMap<>();
prefs.put("download.default_directory", "/tmp/downloads");
options.setExperimentalOption("prefs", prefs);

ChromeDriver driver = new ChromeDriver(options);

常用 Chrome 启动参数速查

参数说明
--headless=new无头模式(新版,Chrome 112+)
--headless无头模式(旧版,兼容性好)
--no-sandbox禁用沙箱(Docker/root 环境必须)
--disable-dev-shm-usage使用 /tmp 替代 /dev/shm(Docker 必须)
--disable-gpu禁用 GPU 加速(无头模式常用)
--window-size=W,H设置窗口大小
--proxy-server=URL设置代理服务器
--ignore-certificate-errors忽略 SSL 证书错误
--disable-extensions禁用所有扩展
--disable-notifications禁用通知弹窗
--disable-popup-blocking禁用弹窗拦截
--lang=zh-CN设置浏览器语言
--user-agent=STRING自定义 UserAgent
--remote-debugging-port=9222启用远程调试端口
--user-data-dir=PATH指定用户数据目录
--profile-directory=NAME指定 Profile
--incognito无痕模式
--kiosk全屏 kiosk 模式
--disable-background-timer-throttling禁用后台定时器节流
--disable-renderer-backgrounding禁用渲染器后台降级

3.6 页面加载策略

WebDriver 协议定义了三种页面加载策略,影响脚本的等待行为:

策略行为适用场景
normal (默认)等待整个页面加载完成(load 事件触发)大多数场景
eager等待 DOM 解析完成(DOMContentLoaded 事件触发)需要快速交互
none不等待任何加载事件完全自定义等待
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.page_load_strategy = 'eager'  # DOM 就绪即可交互

driver = webdriver.Chrome(options=options)
driver.get("https://example.com")  # 不等待图片等资源加载
# 此时即可操作 DOM 元素

3.7 日志与调试

启用 WebDriver 日志

import logging

# 设置 Selenium 日志级别
logging.getLogger('selenium').setLevel(logging.DEBUG)
logging.getLogger('urllib3').setLevel(logging.DEBUG)

获取浏览器日志

options = Options()
options.set_capability("goog:loggingPrefs", {"browser": "ALL"})

driver = webdriver.Chrome(options=options)
driver.get("https://example.com")

# 获取 console.log 输出
logs = driver.get_log("browser")
for entry in logs:
    print(f"[{entry['level']}] {entry['message']}")

ChromeDriver 日志级别

# 启动 ChromeDriver 时指定日志级别
chromedriver --log-level=DEBUG --verbose

# 或通过选项
options.add_argument("--enable-logging")
options.add_argument("--v=1")  # VLOG 级别 (1-9)

3.8 远程 WebDriver

Selenium 支持通过远程 WebDriver 协议控制远端浏览器,这是 Selenium Grid 的基础。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")

# 连接到远程 Selenium Grid / Standalone
driver = webdriver.Remote(
    command_executor="http://selenium-hub:4444/wd/hub",
    options=options
)

driver.get("https://example.com")
print(driver.title)
driver.quit()
远程 WebDriver 工作流:

  测试脚本 ──HTTP──→ Selenium Server ──CDP──→ Chrome
     (本机)          (远程/Grid)          (远程容器)

3.9 Desired Capabilities vs Options

Selenium 4 中推荐使用 Options 替代旧的 DesiredCapabilities

对比DesiredCapabilities (旧)Options (新)
Selenium 3✅ 主要方式⚠️ 有限支持
Selenium 4❌ 已废弃✅ 推荐方式
类型安全有(每个浏览器独立类)
合并能力手动 mergeset_capability()
代码示例caps = DesiredCapabilities.CHROME.copy()options = ChromeOptions()
# ❌ 旧方式 (已废弃)
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
caps = DesiredCapabilities.CHROME.copy()
caps['goog:chromeOptions'] = {'args': ['--headless']}

# ✅ 新方式
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('--headless=new')

3.10 要点回顾

要点说明
Selenium 4 使用 W3C 协议不再依赖 JSON Wire Protocol
ChromeOptions 配置一切启动参数、扩展、实验性选项都通过它设置
页面加载策略影响交互eager 可以提前操作 DOM,none 完全自控
远程 WebDriver通过 HTTP 连接远程浏览器/Selenium Grid
日志调试goog:loggingPrefs 可获取浏览器 console 日志

3.11 注意事项

⚠️ Selenium 4 不向后兼容 Selenium 3: API 有较大变化,迁移时需参考官方迁移指南。

⚠️ --headless vs --headless=new: Chrome 112+ 推荐使用 --headless=new,旧的 --headless 可能缺少某些功能(如扩展加载)。

⚠️ driver.quit() vs driver.close(): quit() 关闭所有窗口并退出浏览器进程,close() 仅关闭当前窗口。务必使用 quit() 避免僵尸进程。

⚠️ --no-sandbox 安全风险: 仅在 Docker 或 root 环境下使用,普通用户不应添加此参数。


3.12 扩展阅读

资源链接
Selenium 官方文档https://www.selenium.dev/documentation/
W3C WebDriver 规范https://www.w3.org/TR/webdriver/
Chrome 启动参数列表https://peter.sh/experiments/chromium-command-line-switches/
Selenium 4 迁移指南https://www.selenium.dev/documentation/webdriver/getting_started/upgrade_to_selenium_4/
ChromeDriver 特性命令行https://chromedriver.chromium.org/capabilities