Lightpanda无头浏览器实战-Playwright接入与Agent化

Lightpanda 实战:一个用 Zig 重写的无头浏览器,怎么接进 Playwright 和 Agent 工作流

结论先放这儿:Lightpanda 的价值不在"又一个更快的浏览器",而在于它把浏览器这个组件在 Agent 系统里的成本结构重新算了一遍。它适合"读和点",不适合"看"。如果你的场景是批量抓取、Agent 工具调用、结构化抽取,它今天就能用;如果你要像素级渲染、视觉回归、复杂 WebGL 页面,它今天不是答案。


一、它到底是什么

GitHub 上 lightpanda-io/browser,截至 2026 年 11 月初约 40.7k stars,在 Zig 语言项目里排第三(前面是 Ghostty 和 Zig 语言本体),GitHub 上每天还有一千多的自然增长。

关键在于它不是 Chromium 的 fork,也不是给 WebKit 打补丁,而是从零写的新内核。作者的动机很实在:团队以前每天要抓几百万网页,跟 headless Chrome 硬碰硬了几年,最后得出一个结论------魔改 Chromium 这条路走不通,必须推翻重来。

它做减法的清单值得单独列一下,因为这决定了后面所有能用和不能用的边界:

砍掉(给人看的部分) 留下(给机器用的部分)
CSS 布局引擎 HTTP 加载(libcurl)
图像解码器 HTML 解析(html5ever)
GPU 合成器 DOM 树(纯 Zig 实现)
字体光栅化 JS 执行(V8)
无障碍树 CDP / WebDriver BiDi 协议层

官方 README 里列的已实现能力:CORS、AJAX(XHR + Fetch)、DOM 与 Markdown dump、CDP/WebSocket 服务端、点击、表单输入、Cookies、自定义请求头、代理、网络拦截、--obey-robots、广告拦截、同时支持 CDP 和 WebDriver BiDi。

这个组合说明一件事:它把"浏览器"重新定义成了"能执行 JS 的 DOM 机"。你能读 DOM、能点、能填表、能拿 JS 执行后的结果,但你看不到它长什么样。


二、性能数字,以及口径

官方基准用的是 AWS EC2 m5.large,抓 933 个真实网页,取其中 100 页的任务:

指标 Headless Chrome Lightpanda 差距
100 页耗时 46s 5s 约 9 倍
峰值内存 约 2GB 123MB 约 16 倍
冷启动 数秒 基本瞬时 ---

需要说清楚的是,官方不同位置的口径并不完全一致:官网首页写的是 "10x faster, 10x less memory",README 标的是 "16x lighter and 9x faster",更新的基准页出现过 11x / 9x。这些数字都对应同一套 AWS m5.large 的方法学,差异来自哪一轮跑的数据。能复现是它比大多数营销数字靠谱的地方------测量用的 demo 仓库是公开的,你可以自己跑一遍。

另一个容易被忽略的指标是内存搁浅 。Chromium 那 2GB 里有相当一部分是跑完不还给系统的分配器碎片,这也是为什么长期跑 Chrome 容器的机器内存曲线会一路爬。Lightpanda 用 mimalloc 加上 mallopt / trim 那套处理,把这块压下来了。真要上规模,这部分比"快 9 倍"更值钱。


三、四种接入方式,先选对入口

很多人第一次看文档会晕,因为它同时提供了四条路。按用途分就清楚了:

方式 入口 适用场景 要 LLM 吗
CLI fetch lightpanda fetch --dump ... 单页取内容、写进 shell 管线 否
CDP 服务 lightpanda serve --port 9222 已有 Playwright / Puppeteer 脚本 否
原生 MCP lightpanda mcp Agent 客户端(Claude Desktop、Cursor 等) 由客户端决定
Agent 模式 lightpanda agent 自然语言驱动、探索式抓取 是(可 --no-llm)

一句话选路:一次性取内容用 fetch,程序化控制用 CDP,接 Agent 用 MCP,不想写代码用 agent。

先看最省事的 CLI。除了 html/markdown,它还能直接 dump 语义树和结构化数据,并且支持按选择器裁、按噪声类型剥:

bash 复制代码
# 取正文 Markdown,只保留 main,剥掉导航和广告,超 40KB 截断
lightpanda fetch \
  --dump markdown \
  --dump-selector "main" \
  --strip-mode clutter \
  --dump-max-bytes 40000 \
  https://example.com/article > page.md

# 直接出 JSON-LD / OpenGraph / meta
lightpanda fetch --dump structured_data https://example.com/product

# 懒加载页面:等选择器出现再 dump
lightpanda fetch --wait-selector ".price" --dump markdown https://shop.example.com/p/1

--dump 支持 html、markdown、png、pdf、semantic_tree、semantic_tree_text。其中 png/pdf 是纯文本排版,不是像素级渲染------这点务必记牢,后面会反复出现。


四、用 Playwright 操纵它

这是最多人问的部分。核心只有一句:用 playwright-core,走 connectOverCDP,不是 launch。

先起服务:

bash 复制代码
./lightpanda serve --host 127.0.0.1 --port 9222
curl http://127.0.0.1:9222/json/version   # 探活

然后连接:

js 复制代码
import { chromium } from 'playwright-core';

const browser = await chromium.connectOverCDP({ endpointURL: 'ws://127.0.0.1:9222' });
const context = await browser.newContext();   // 必须显式创建
const page = await context.newPage();

await page.goto('https://example.com');
console.log(await page.title());

await page.close();
await context.close();
await browser.close();

Python 一样,端点用 http:// 也行:

python 复制代码
browser = await p.chromium.connect_over_cdp("http://127.0.0.1:9222")

两个前置提醒:装 playwright-core 而不是完整 playwright 包 (后者会顺手下载几百 MB 的浏览器,这里一个都用不上);ws:// 和 http:// 两种端点都接受。

五条硬约束,不知道就会白折腾

这是我踩过一轮之后总结的,按重要性排序:

1. 一个进程 = 一条 CDP 连接 = 一个 context = 一个页面。

不是"建议",是硬限制。第二次 newContext() 会直接失败。没有多 tab 这回事。

2. 连接一断,上下文全清。

所以整个抓取会话要保持 WebSocket 不断,中间别重连。想去"恢复现场"是徒劳的,重连就是干净的新世界。

3. 没有渲染引擎。

page.screenshot() 拿不到有意义的像素,viewport、deviceScaleFactor 这类参数等于摆设,任何依赖 CSS 布局计算的断言都不成立。

4. 部分 Playwright API 没实现,会直接抛错。

官方给的建议很直白:抛错就退回 page.evaluate(),在页面里自己算。别试图找兼容层,没有。

5. Google 会拦它。

原因不是 IP,是指纹不像真浏览器。做搜索类抓取请用 DuckDuckGo 或 Bing,别在 Google 上浪费调试时间。

并发:多进程,不是多标签

承接第 1 条限制,正确的并发形态是:

ini 复制代码
1 个端口 = 1 个进程 = 1 条连接 = 1 个 context = 1 个页面
要 20 并发 → 起 20 个 lightpanda serve,端口 9222 到 9241

听起来很暴力,但因为冷启动几乎为零、单实例内存只有几十 MB,多进程反而比 Chrome 的多 tab 更划算------Chrome 里 20 个 tab 共享一个巨大的浏览器进程,一个页面崩了大家一起崩;Lightpanda 里 20 个进程互相隔离,挂一个不影响别人,还能按需销毁重建。

这也是它能做多租户隔离的底气:每个连接的 V8 isolate 独立、线程亲和,断开即回收。


五、真正值钱的东西:LP 私有 CDP 域

如果只有"兼容 Playwright",它就是个更省内存的 Chrome 替代品。真正的差异在这四个命令上------它们是 Lightpanda 自己扩展的 CDP 域,Chrome 上没有:

命令 产出 Token 成本 关键优势
LP.getMarkdown 页面正文 Markdown 中 去排版噪声,保留标题层级和链接
LP.getSemanticTree 精简语义树 低 带 XPath,能直接定位后续操作
LP.getInteractiveElements 可交互元素扁平列表 低 带监听类型和 nodeId,直接点
LP.getStructuredData JSON-LD / OG / meta 低 机器可读元数据,一次调用拿全

用法是单开一个 CDP session:

js 复制代码
const cdp = await context.newCDPSession(page);

const { markdown }       = await cdp.send('LP.getMarkdown');
const { tree }           = await cdp.send('LP.getSemanticTree', { format: 'json', prune: true });
const { elements }       = await cdp.send('LP.getInteractiveElements');
const { structuredData } = await cdp.send('LP.getStructuredData');

为什么这比在 Node 里 page.content() 再上 cheerio / readability 强?因为转换发生在浏览器内部 。整页 HTML 不出内核,省掉的是"序列化 → 跨进程传输 → JS 解析 → 清洗"这一整条链路, tokentoken token 和带宽都省。做 LLM 抽取时,LP.getMarkdown 的输出基本可以原样塞进 prompt。

这背后是一种设计立场的转变:标准 CDP 是为调试设计的 ,满是给开发者看的中间态;LP 域是为机器设计的,一次调用直接产出最终形态。做 Agent 的人应该能立刻看出这个区别的价值。


六、Agent 模式:让浏览器自己干活

这是它区别于所有"Chrome 包装器"的第二层。不写代码,直接对话:

bash 复制代码
lightpanda agent                                                    # 进 REPL
lightpanda agent --task "top story on news.ycombinator.com?"        # 一次性任务
lightpanda agent --no-llm                                           # 纯斜杠命令,不烧 token
lightpanda agent --list-models                                      # 看当前 provider 的可用模型

REPL 里两种驱动方式混用:自然语言,或者斜杠命令 /goto、/links、/model、/effort、/save、/load。

Provider 覆盖面很宽:Anthropic、OpenAI、Gemini、Vertex、Mistral、Hugging Face、Vercel AI Gateway、OpenRouter、任意 OpenAI 兼容端点、Ollama、llama.cpp。默认从环境变量自动认 key,单个 key 直接生效,多个 key 在 TTY 下会让你选。

国内环境最顺的是 openai_compatible 这条路------火山方舟、各种中转网关都能接:

bash 复制代码
export OPENAI_BASE_URL="https://ark.cn-beijing.volces.com/api/v3"
export OPENAI_API_KEY="$ARK_API_KEY"
lightpanda agent --provider openai_compatible --model "<endpoint-id>" \
  --task "打开 news.ycombinator.com,取头条标题和分数,只输出 JSON"

其他有用参数:--effort 控制每轮推理预算(none / minimal / low / medium / high / xhigh,REPL 默认 low 求快,one-shot 默认 medium);--attach 可以把本地文件(文本、图片、音频、PDF)一并喂给模型配合 --task 使用。

最值得抄的设计:/save 导出可回放脚本

vbnet 复制代码
❯ go to news.ycombinator.com and get me the top story title and points
...(Agent 导航、抽取、打印答案)
❯ /save session.js

退出后用无 LLM 的方式回放:

bash 复制代码
lightpanda run session.js
cat session.js | lightpanda run -    # 从管道喂

这一步是整个设计里最聪明的地方:把 LLM 的不确定性收敛成确定性脚本。探索阶段用模型,生产阶段用脚本,token 成本归零,行为可复现、可 diff、可进 CI。

对做过爬虫的人应该很眼熟------这就是"录制回放"思路在 Agent 时代的复活。比起每次都让模型重新摸索一遍 DOM,这套结构省下的不只是钱,还有排障时间。

安全上有个必须说清楚的:导出的 .js 里可以包含 evaluate(...),等于任意页面内 JS 执行。别跑来源不明的脚本,跟 shell 脚本同等对待。


七、MCP:不写自动化库,直接接 Agent

如果 Agent 框架本身说 MCP,那连 Playwright 都不用装。Lightpanda 把 MCP server 编进了二进制:

json 复制代码
{
  "mcpServers": {
    "lightpanda": {
      "command": "/usr/local/bin/lightpanda",
      "args": ["mcp"]
    }
  }
}

stdin/stdout 走 JSON-RPC 2.0。暴露的工具集:

工具 作用
goto 导航并把页面载入内存
markdown 页面转 token 友好的 Markdown(同 LP.getMarkdown)
semantic_tree 精简后的可交互 DOM 表示(同 LP.getSemanticTree)
links 抽取全部链接
interactiveElements 按钮、输入框等可操作元素
structuredData JSON-LD / OG / 语义元数据
evaluate 在页面上下文执行任意 JS

外加两个资源:mcp://page/html(原始 DOM)、mcp://page/markdown(清洗后正文)。

还有个容易被忽略的细节:MCP server 直接调 Zig 引擎里的能力,没有中间翻译层 。之前官方有个 gomcp,是 Go 写的 MCP→CDP 桥接,能用,但链路是 MCP 客户端 → gomcp → CDP → Lightpanda,多一轮序列化。现在编进二进制,一层就到底了。

要远程/多客户端,用 HTTP 形态:

bash 复制代码
lightpanda mcp --port 9223      # POST http://127.0.0.1:9223/mcp

每个客户端靠 Mcp-Session-Id 头隔离会话。


八、插件与 Skill 生态:能力已经溢出到宿主侧

Lightpanda 官方维护了一个 lightpanda-io/agent-skill,给 Claude Code 这类支持 Skill 的客户端用。社区这边的封装更活跃,形态基本是"把 CDP 包成一组细粒度工具"。

拿 pi-lightpanda 这个第三方插件举例,它的工具设计挺有参考价值:

工具 用途
lightpanda_fetch 只读抓取,先看内容再决定要不要操作
lightpanda_navigate 导航到目标页
lightpanda_snapshot 生成带 ref 的可交互快照
lightpanda_act click / fill / type / select / press / hover
lightpanda_extract 按 CSS 选择器抽命名字段,返回 JSON
lightpanda_eval 页面内执行 JS
lightpanda_run 执行可信的 .js 脚本(等价 lightpanda run)

里面有两个工程细节值得单独拎出来:

一是 host guard 只允许回环地址。 因为 CDP 端点能控制 cookies 和会话,没有任何鉴权,暴露到公网等于把自己的浏览上下文交给别人。这条不是保守,是必须。

二是 extract 工具明确"不猜" :选择器必须由 Agent 提供,工具不推断;匹配结果区分 ok / missing / ambiguous / redacted / error;一个选择器默认必须精确匹配一个元素,要列表得显式 many: true。价格这类字段原样返回字符串,不做货币换算、不做类型转换。

这个设计思路值得抄:抽取层只负责"如实取出",不负责"猜你的意思"。歧义就报歧义,缺就报缺,让 Agent 去决定下一步。比起"尽力猜一个看起来合理的值",后者在数据管线里是灾难。


九、什么情况下不要用它

这部分比优点更需要读完。

1. 需要像素级渲染、视觉回归、WebGL / 3D 页面 ------ 不行,短期内也不会。

它连布局引擎都没有,这不是 roadmap 优先级问题,是设计取舍。要做截图对比、端到端视觉测试,继续用 Chrome。

2. 闭源商业嵌入 ------ AGPL-3.0 是红线。

AGPL 是网络型 copyleft,只要你把修改后的版本作为网络服务提供出去,就必须开源。想塞进闭源产品里当组件卖,基本堵死。这条对做 SaaS 的人影响最大,动手前先读许可。

3. 只抓静态 HTML 的页面 ------ 纯浪费。

没有 JS 要执行,curl 或 fetch 永远更快更省。判断标准很简单:这页关了 JS 还能不能看?能,就别上浏览器。

4. Windows 原生环境 ------ 没有二进制。

官方只出 Linux(x86_64 / aarch64)和 macOS。Windows 只能在 WSL2 里跑,localhost:9222 会自动转发到宿主。另外 Linux 二进制链接的是 glibc,Alpine 这类 musl 发行版得换基础镜像或自己编译。

5. 兼容性仍然是 Beta 水平。

README 自己写着"预期大部分网站会失败或崩溃",WPT 通过率是一格一格啃上来的。复杂 SPA、深度依赖浏览器 API 的站点,跑之前先假设它会挂,做好降级到 Chrome 的开关。

另外两个小坑:默认开启遥测 ,介意的话设 LIGHTPANDA_DISABLE_TELEMETRY=true;Docker 镜像只适合 serve 和 fetch,agent 模式要带 LLM 配置,直接在宿主机装二进制更省事。


十、结论

用一句话当判据:你的浏览器是用来"看"的,还是用来"读和点"的?

场景 用不用
大规模抓取、高并发采集 用,内存账单直接降一个数量级
给 Agent 接网页能力(MCP) 用,工具设计就是奔着这个去的
结构化数据抽取 用,LP.getStructuredData + getMarkdown 省 token
LLM 训练语料收集 用,动态页也能拿到 JS 执行后的内容
CI 冒烟测试(非视觉) 用,快、隔离好
视觉回归 / 截图对比 不用,没有渲染
复杂 WebGL / 3D 页面 不用
闭源商业嵌入 不用,AGPL
纯静态页抓取 不用,curl 更快

它没有试图做一个"更好的浏览器",而是把浏览器的成本结构拆开重新算了一遍:冷启动编译进二进制、内存搁浅靠分配器治理、热点代码按页重排、多租户靠 isolate 线程亲和、LLM 的不确定性靠脚本收敛。每一个选择都有代价,而且代价写得很诚实------没有 WebGL、截图不是像素级、平台支持窄、AGPL 有合规门槛、默认开遥测。

开源项目里少见的品质:它知道自己不是什么。


数据与来源

  • 仓库:github.com/lightpanda-io/browser(AGPL-3.0),star 数与 Zig 项目排名数据截至 2026-11-02
  • 基准方法学:AWS EC2 m5.large,933 个真实网页,100 页任务;测量脚本在官方 demo 仓库,可复现
  • Playwright / Puppeteer 连接方式与"一个连接一个上下文一个页面"限制:官方博客 How We Built MultiClient into Lightpanda
  • LP 私有域四个命令与工具语义:官方博客 New LP Domain Commands and Native MCP
  • Agent 模式参数、provider 列表、/save 回放机制:官方文档 lightpanda.io/docs/reference/cli/agent
  • pi-lightpanda 工具设计:第三方 npm 包文档,非官方
相关推荐
kaixin_啊啊21 分钟前
【零基础学AI】第 24 章课后练习与答案
人工智能
EchoMind-Henry21 分钟前
娱乐资本论发布AI短剧剧本对比文章
人工智能·娱乐
hkNaruto26 分钟前
【AI】游戏大模型智能体OODA过程记忆问题解决方案:AgenticSTS 有界记忆契约:技术分析与流水线改造操作手册
人工智能·游戏·机器学习
杜子不疼.30 分钟前
没有真机,我给启元 Q1 造了一台“假机器人“:官方 SDK 示例跑通实录
人工智能·机器人
qq_2803914936 分钟前
温度参数设置建议
人工智能
qq_280391491 小时前
Java构建飞书消息格式详解
人工智能
Flynn Liang2 小时前
上线后怎么排查 AI 调用?Spring AI Observability:token/延迟/成本埋点与全链路追踪
java·人工智能·spring·监控·可观测性·observability·springai
测试界的小码农2 小时前
【让 AI 生成的测试用例变成 pytest API 自动化脚本】
人工智能·测试用例·pytest
天天代码码天天3 小时前
我开源了一个家庭备份工具:把手机照片和视频,存回自己的电脑
人工智能