← 文章 / 编程开发
lightpanda 1小时前 · 2026-10-08 01:11:56 · 6 阅读

加快您的 Selenium 脚本运行速度:Lightpanda 现已支持 WebDriver

Céline Debled
Speed up your Selenium scripts: Lightpanda now speaks WebDriver

Lightpanda 1.0 现已支持 WebDriver,包括经典版和 BiDi 版本,成为唯一能原生运行所有 Web 自动化协议的浏览器:CDP、WebDriver 和 MCP。只需将 Selenium 脚本指向 lightpanda serve --protocol webdriver 而非 chromedriver,或者使用 lightpanda Python 包自动启动它,脚本即可无需任何修改直接运行。在目前 Lightpanda 支持的 Selenium 官方文档测试中,它比无头版 Chrome 快最高 4.4 倍,内存占用少 7 倍。WebDriver 支持仍在完善中,大家的测试用例将决定我们下一步的开发方向。

WebDriver、CDP 和 BiDi:三种协议,多种客户端

如果你现在运行 Selenium 脚本,那么你已经在用 WebDriver 了。Selenium 是一个客户端库,而WebDriver 是它所使用的通信协议,源自 Selenium 项目,已发展为 W3C 标准。目前控制浏览器主要靠三种协议:

协议通信方式制定者主要客户端
WebDriver 经典版HTTP。浏览器只回复请求,因此客户端需轮询以获取变更W3CSelenium、WebdriverIO、Nightwatch、Appium
WebDriver BiDiWebSocket,双向开放。浏览器主动推送事件W3C,仍在草案阶段Selenium 4 BiDi API、WebdriverIO、Puppeteer
CDPWebSocket,双向开放。浏览器主动推送事件Google,专用于 Chromium 系浏览器Puppeteer、Playwright、chromedp、Rod

How test clients reach each browser: Selenium goes through chromedriver, geckodriver or safaridriver, Puppeteer and Playwright speak CDP to Chrome, and both connect to Lightpanda directly with no driver

选择哪种协议,决定了你的脚本和浏览器之间隔着什么。

WebDriver 出现得最早。它于 2011 年并入 Selenium,2018 年成为 W3C 标准。测试脚本通过 HTTP 向 driver 发送命令,而每家浏览器厂商都有自己的实现:Chrome 用 chromedriver,Firefox 用 geckodriver,Safari 用 safaridriver。这个 driver 是额外多出来的一个进程,每次运行都得和浏览器一起安装、启动。

与此同时,Chrome 自研了一套协议。从 2012 年起,DevTools 协议(CDP)就能让检查器面板通过 WebSocket 控制页面,浏览器可以在事件发生时实时推送。它基于 Chrome 内部机制设计,覆盖的功能远不止自动化。2017 年,Chrome 团队在它之上构建了 Puppeteer,随后 Playwright 也加入进来,CDP 成了事实上的自动化标准。想深入了解它的工作原理,可以看看 CDP under the hood 这篇文章。

WebDriver BiDi 目前还是 W3C 草案,试图兼得两者之长:用 WebSocket 实现双向通信,同时是一个任何浏览器都能实现开放标准。不过 driver 依然存在:在 Chrome 上,chromedriver 仍负责开启会话,并把 BiDi 翻译成 CDP。

我们在此前文章中更详细地介绍过 web automation stack 及其整体架构。

Lightpanda 原生支持所有 Web 自动化协议

启动 Lightpanda 项目时,我们思考了一个问题:如果浏览器是为机器而生,它应该是什么样子?我们的答案是:不做图形渲染,让代码直接控制浏览器,中间不需要任何 driver。

最初,Lightpanda 支持 CDP,因此 Puppeteer 和 Playwright 脚本从一开始就能在其上运行。1.0 版本新增了对 WebDriver(经典版和 BiDi)的支持,让你的 Selenium 测试套件也能在此运行。现在,Lightpanda 是唯一原生支持所有主流 Web 自动化协议的浏览器:CDP、WebDriver 和 MCP。

在 Lightpanda 上运行 Selenium 测试套件

你需要:

  • Python 3 环境,安装 Selenium 和 pytest:pip install selenium pytest
  • Lightpanda 1.0 或更高版本(参见安装指南):
curl -fsSL https://pkg.lightpanda.io/install.sh | bash -s "1.0.0"

示例针对 quotes.toscrape.com(一个公开的练习网站)运行两个测试。test_login 提交登录表单并等待出现 Logout 链接。test_js_rendered_quotes 检查在页面加载后由 JavaScript 注入的引言。

conftest.py 包含为每个测试打开新 WebDriver 会话的 pytest fixture。这是唯一需要针对 Lightpanda 特殊处理的代码:webdriver.Remote 让 Selenium 连接到正在运行的 Lightpanda 服务器,而不是启动 chromedriver。

# conftest.py
import pytest
from selenium import webdriver
 
 
@pytest.fixture
def driver():
    # `lightpanda serve --protocol webdriver` 默认监听 9222 端口。
    d = webdriver.Remote(
        command_executor="http://127.0.0.1:9222",
        # Selenium 需要一个 options 对象;Lightpanda 接受任意浏览器的 options。
        options=webdriver.ChromeOptions(),
    )
    yield d
    d.quit()

test_quotes.py 包含测试用例。它们是标准的 Selenium 代码,无需修改即可在 Chrome 上运行。

```html
# test_quotes.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
 
BASE = "https://quotes.toscrape.com"
 
 
def test_login(driver):
    driver.get(f"{BASE}/login")
    driver.find_element(By.ID, "username").send_keys("panda")
    driver.find_element(By.ID, "password").send_keys("secret")
    driver.find_element(By.CSS_SELECTOR, "input[type=submit]").click()
    logout = WebDriverWait(driver, 5).until(
        EC.presence_of_element_located((By.LINK_TEXT, "Logout"))
    )
    assert logout.text == "Logout"
 
 
def test_js_rendered_quotes(driver):
    # /js/ 页面上的引语由 JavaScript 注入,HTML 源码中不包含这些内容。
    driver.get(f"{BASE}/js/")
    quotes = WebDriverWait(driver, 5).until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".quote"))
    )
    assert len(quotes) == 10
    assert driver.find_element(By.CSS_SELECTOR, ".quote .author").text == "Albert Einstein"

在第二个终端中启动 Lightpanda 的 WebDriver 模式,然后运行测试套件:

lightpanda serve --protocol webdriver
pytest -v
collected 2 items

test_quotes.py::test_login PASSED                                        [ 50%]
test_quotes.py::test_js_rendered_quotes PASSED                           [100%]

============================== 2 passed in 1.20s ===============================

使用 Lightpanda Python 包

如果不想手动安装浏览器,可以使用 lightpanda 包。该包内置了 Lightpanda 并会自动为你启动服务器。保留原有的 test_quotes.py,并替换 conftest.py 为以下内容:

pip install lightpanda selenium pytest
# conftest.py
import pytest
from lightpanda import BiDiServer
from selenium import webdriver
 
 
@pytest.fixture(scope="session")
def server():
    # 启动包内附带的 Lightpanda 可执行文件
    with BiDiServer() as server:
        yield server
 
 
@pytest.fixture
def driver(server):
    d = webdriver.Remote(server.http_endpoint, options=webdriver.ChromeOptions())
    yield d
    d.quit()

然后运行 pytest -v。

基准测试:Selenium 官方测试在 Chrome 与 Lightpanda 上的表现

```

我们跑了 Selenium 文档背后的 Python 示例,目标是其中 66 个使用标准 WebDriver 命令的测试,且只改了 conftest.py 里的 driver 配置。测试页面在本地提供服务,因此网络耗时不会影响数据。

Lightpanda 通过了 66 个测试中的 43 个(Chrome 为 65 个)。失败的测试用到了我们仍在开发的功能,详见下文Lightpanda 1.0 目前支持的功能。我们对双方都能通过的 43 个测试计时,每个重复 3 次,分别测了单个串行运行和 8 个并行运行:

Lightpanda 1.0.0Chrome 154 + chromedriver
单个串行40.8 秒,74 MB105.2 秒,552 MB
8 个并行12.1 秒,97 MB53.8 秒,759 MB

串行运行时,Lightpanda 快 2.6 倍,内存少 7.5 倍;8 个并行时,快 4.4 倍,内存少 7.8 倍。原因是每个 Chrome 会话都要启动独立的进程树,而 Lightpanda 的会话只是单个运行进程中的一个上下文。

以上结果是 5 次运行的中位数,环境为 GitHub Actions Linux runner(2 核 CPU、8 GB 内存),对标 headless Chrome 154。脚本和具体版本见这个 Gist。

在 CI 中运行的技巧

在测试开始前先在后台启动服务,它几乎瞬间就能就绪:

lightpanda serve --protocol webdriver &
pytest

如果你的测试需要并行执行,记得调高会话上限。pytest-xdist(pytest -n)或 Selenium Grid 这类工具会为每个 worker 开一个会话,而 Lightpanda 默认最多同时接受 16 个。可以把 --cdp-max-connections(同样适用于 WebDriver 会话)设为 worker 数量的 1.5 倍左右,因为已关闭的会话需要时间才能释放槽位。以 32 个 worker 为例:

lightpanda serve --protocol webdriver --cdp-max-connections 48

在每个测试结束时都要调用 driver.quit()。用 Chrome 时,未关闭的会话会随 pytest 进程一起终止;但在使用共享的 Lightpanda 服务器时,该会话槽位会一直保留,直到触发 60 秒的空闲超时机制。如果堆积了太多这样的残留会话,下次运行就会因 too many sessions(会话过多)而失败。

Lightpanda 1.0 目前支持的功能

下表对比了 Lightpanda 在不同协议下的支持情况。

能力Classic 协议BiDi 协议
会话(每个测试一个)✅✅
导航✅ get, back, forward, refresh⚠️ 仅支持 navigate
查找元素✅ CSS, ID, XPath, 链接文本✅ l
原始来源: lightpanda

评论 (0)