- 开发工具
- CLI
- 人工智能
- AI 应用
- 浏览器控制
- GUI 自动化
【免费下载链接】OpenCLI
Make Any Website into CLI & Use your logged-in browser by AI agent.
本文以 OpenCLI 仓库中 SMZDM 适配器的官方文档(docs/adapters/browser/smzdm.md)为核心骨架,系统讲解如何复用你已登录的 Chrome 会话,通过
opencli smzdm search命令在终端中搜索什么值得买(smzdm.com)的优惠好价。文章完整覆盖命令用法、运行前置条件,并深入 搜索适配器源码 与 测试用例,剖析其"浏览器内 DOM 抓取 + 可信链接白名单 + 指标归一化"的实现原理,帮助你理解这类 Browser 模式适配器在 OpenCLI 中的工作方式,并可直接复制命令上手使用。
一、适配器概览:🔐 Browser 模式与 smzdm.com 域
什么值得买(SMZDM)适配器在 OpenCLI 中以独立的命令集形式存在,其元信息如下:
- 模式(Mode):🔐 Browser —— 表示该适配器属于浏览器型,需要复用你本机 Chrome 中已登录的会话;
- 域(Domain):
smzdm.com; - 当前命令:
opencli smzdm search(什么值得买搜索好价)。
从仓库目录结构看,该适配器包含两个核心文件:
| 文件 | 作用 |
|---|---|
| clis/smzdm/search.js | 命令实现:声明命令元信息、参数,并通过浏览器执行页面内抓取脚本 |
| clis/smzdm/search.test.js | 基于 jsdom + Vitest 的单元测试,覆盖抓取、参数校验、URL 白名单等关键行为 |
该适配器整体属于只读(read)访问命令:只负责搜索并返回好价列表,不涉及发帖、点赞、收藏等写操作。
二、命令用法:opencli smzdm search
官方文档给出的完整用法如下:
# 快速开始:搜索并返回前 5 条结果 opencli smzdm search --limit 5 # JSON 输出 opencli smzdm search -f json # Verbose 模式(打印详细日志) opencli smzdm search -v从 clis/smzdm/search.js 的命令声明中可以确认该命令的完整参数契约:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
query | 位置参数(string) | ✅ | 无 | 搜索关键词 |
limit | int | ❌ | 20 | 返回结果条数,取值范围1~100 |
limit的解析与校验逻辑集中在parseLimit()函数中(clis/smzdm/search.js),其行为要点:
- 未传时默认
20;数字或纯数字字符串会被接受; - 非整数、非有限值,或超出
1~100范围时抛出ArgumentError; - 参数校验在发起浏览器导航之前完成——测试用例
'validates --limit before browser navigation'(clis/smzdm/search.test.js)通过 mock 的page.goto验证了limit: 0、limit: 101、limit: '1e2'均会抛错且不会触发任何页面跳转。
一个完整可复制的实战示例:
# 搜索"笔记本",输出前 10 条好价,JSON 格式 opencli smzdm search 笔记本 --limit 10 -f json # 搜索"咖啡"并查看详细日志 opencli smzdm search 咖啡 -v三、运行前置条件:登录会话与 Browser Bridge
官方文档明确列出了两项前提条件:
- Chrome 正在运行,并且已登录 smzdm.com;
- 已安装 Browser Bridge 扩展(对应仓库文档 docs/guide/browser-bridge.md)。
3.1 为什么必须登录 Chrome
SMZDM 适配器使用Strategy.COOKIE策略。从 src/registry.ts 中的Strategy枚举可以看到,COOKIE表示"需要登录态(needs login)"的命令。其执行时的核心前提是复用你 Chrome 中现有的登录 Cookie——这正是 SMZDM 搜索结果页可能要求登录后才能完整展示的原因。
关于策略归一化,src/registry.ts 还给出了一个关键推断:当命令声明COOKIE策略且带有domain时,navigateBefore会被自动推导为该域的 URL(例如本适配器声明了domain: 'www.smzdm.com'),意味着执行命令前会先导航到站点域,确保浏览器会话处于正确的站点上下文中。
3.2 Browser Bridge 的安装与验证
Browser Bridge 是一个轻量的 Chrome 扩展 + 微守护进程组合(零配置、自动启动)。安装方式(详见 docs/guide/browser-bridge.md):
方法一:加载预构建 Release(推荐)
- 下载最新版
opencli-extension-v{version}.zip; - 解压后打开
chrome://extensions,开启右上角开发者模式; - 点击加载已解压的扩展程序,选择解压后的目录。
方法二:加载源码目录(开发者)
- 打开
chrome://extensions并开启开发者模式; - 选择仓库中的 extension/ 目录加载。
安装完成后可用以下命令一键验证连通性:
opencli doctor # 检查扩展 + 守护进程连接状态该扩展在 extension/README.md 中说明了其权限用途:debugger用于向 OpenCLI 控制的标签页发送 CDP 命令,cookies用于读取浏览器 Cookie 以支持需要认证的适配器请求,tabs/tabGroups用于管理自动化容器。
四、底层原理:从搜索页 URL 到结构化结果
SMZDM 适配器最值得关注的是它的实现演进与抓取策略。源码头部注释(clis/smzdm/search.js)记载了关键背景:
旧版适配器使用
search.smzdm.com/ajax/接口,该接口现已返回 404;新方案改为直接导航到https://search.smzdm.com/?c=home&s=<keyword>&v=b,对渲染后的 DOM 进行抓取。
这正是"网页改版导致接口失效 → 退化为浏览器内 DOM 抓取"的典型实战案例。
4.1 执行调用链
命令执行函数(clis/smzdm/search.js)的完整调用链为:
- 对关键词做
encodeURIComponent编码; - 通过
parseLimit解析并校验limit; page.goto导航到搜索结果页 URL:https://search.smzdm.com/?c=home&s=${q}&v=b;page.evaluate在页面上下文中执行buildSmzdmSearchJs(limit)生成的内联抓取脚本;- 抓取结果经过
requireSearchRows校验后返回。
4.2 页面内抓取脚本的关键实现
buildSmzdmSearchJs()(clis/smzdm/search.js)生成一段在浏览器页面上下文中执行的 IIFE,其核心逻辑包括:
DOM 选择器映射:
| 目标字段 | 选择器 |
|---|---|
| 结果条目容器 | li.feed-row-wide |
| 标题 | h5.feed-block-title > a(回退h5 > a) |
| 价格 | .z-highlight |
| 商城 | .z-feed-foot-r .feed-block-extras span(回退.z-feed-foot-r span) |
| 更新时间 | .z-feed-foot-r .feed-block-extras的直接文本节点 |
交互指标归一化(normalizeCount):SMZDM 页面上的赞、不值、收藏、评论数常以"1.2万"、"3"、"24"等中文/英文单位展示。脚本通过正则(\d+(?:\.\d+)?)\s*([万kK]?)解析数值,并按单位换算:万→ ×10000,k/K→ ×1000,其余四舍五入取整。测试用例(clis/smzdm/search.test.js)验证了1.2万 → 12000的换算结果。
可信 URL 白名单(trustedSmzdmUrl):为防止输出外部恶意链接,脚本仅接受https:协议且主机名属于www.smzdm.com或post.smzdm.com的链接;相对路径会基于https://www.smzdm.com解析。测试用例'drops untrusted result URLs before output'(clis/smzdm/search.test.js)验证了https://evil.example/...这类链接会被整体过滤,该条目不会出现在结果中。
字段完整性保证:脚本注释特别强调——每条结果都携带完整的声明的列集合,当列表项缺失交互指标时默认置0、更新时间置'',确保任何列都不会被静默丢弃。测试用例'defaults missing interaction metrics to 0 without dropping columns'(clis/smzdm/search.test.js)验证了这一点。
4.3 输出列结构
命令声明的输出列为(clis/smzdm/search.js):
rank, title, price, mall, updated_at, zhi_count, buzhi_count, favorite_count, comments, url各字段含义:
| 列 | 含义 |
|---|---|
rank | 结果序号(从 1 开始) |
title | 好价标题 |
price | 价格文本(如4015.44元(需用券)) |
mall | 商城来源(如天猫精选) |
updated_at | 更新时间(如05-23 00:28) |
zhi_count | "值"(点赞)数量,万/k已归一化为整数 |
buzhi_count | "不值"数量 |
favorite_count | 收藏数 |
comments | 评论数 |
url | 经过白名单校验的绝对链接 |
4.4 结果封装解包与失败兜底
命令返回的抓取结果可能带有 Browser Bridge 的{ session, data }封装(unwrapEvaluateResult,clis/smzdm/search.js 负责解包);随后requireSearchRows(clis/smzdm/search.js)会强制校验返回值为数组,否则抛出CommandExecutionError。测试用例'fails closed on malformed extraction payloads'(clis/smzdm/search.test.js)验证了"畸形载荷一律失败关闭"的兜底策略,避免静默返回错误数据。
五、测试验证:行为如何被守护
clis/smzdm/search.test.js 使用 jsdom + Vitest 对抓取脚本做离线验证(runBrowserScript通过dom.window.eval直接执行生成的抓取脚本),共覆盖六个维度:
- 元信息声明:
access为read,列集合与预期一致; - 完整字段抓取:价格、商城、更新时间、四项交互指标均正确提取并归一化;
- 缺失字段兜底:无指标条目默认置
0/空串,列不丢失; - URL 白名单:非 smzdm.com 域名的链接被整体丢弃;
- limit 生效:
buildSmzdmSearchJs(2)在 5 个条目的页面上只返回 2 条,且rank为[1, 2]; - 参数预校验:非法
limit在浏览器导航前抛出ArgumentError。
这些测试既是行为的守护,也是理解适配器边界条件的绝佳示例——尤其是"URL 白名单"与"字段缺省兜底"这两项,直接体现了浏览器适配器在生产环境中的可靠性设计。
六、常见问题与排查建议
结合源码与运行前提,汇总几条实际使用中的排查思路:
- 命令报"需要登录"或结果为空:确认 Chrome 处于运行状态、已登录 smzdm.com,且登录会话有效。浏览器适配器复用的是 Chrome 的登录 Cookie,未登录时搜索页内容可能不完整;
opencli doctor显示扩展/守护进程异常:按 docs/guide/browser-bridge.md 重新加载扩展,确认chrome://extensions中开发者模式已开启;- 结果缺少价格或指标:这属于正常兜底行为——当页面 DOM 未包含对应节点时,指标默认置
0、时间置空串,但列结构保持不变; - 返回 URL 变少:非
www.smzdm.com/post.smzdm.com域名的链接会被白名单过滤,属于预期行为。
如需在其他 Browser 模式适配器间横向对比(如小红书、知乎、值得买等),可参考 docs/adapters/browser/ 目录下的对应文档;扩展本身的权限设计与自动化容器约定详见 extension/README.md。
七、小结
SMZDM 适配器是理解 OpenCLIBrowser 模式适配器的一个高质量范例:它展示了一条完整的技术路径——从"登录 Chrome 会话 + Browser Bridge 桥接"的前置条件,到"直接导航搜索页 + 页面内 DOM 抓取"的实现策略,再到"指标归一化、URL 白名单、字段缺省兜底、畸形载荷失败关闭"等可靠性设计。通过本文,你不仅可以直接在终端中使用opencli smzdm search搜索好价,也掌握了这类"网页改版导致接口失效后改走 DOM 抓取"的适配器在 OpenCLI 中的实现与测试套路,可作为编写或维护同类适配器的参考。
- 开发工具
- CLI
- 人工智能
- AI 应用
- 浏览器控制
- GUI 自动化
【免费下载链接】OpenCLI
Make Any Website into CLI & Use your logged-in browser by AI agent.
相关推荐
OpenCLI LinkedIn Learning 适配器实战:基于浏览器 Cookie 会话的课程搜索与详情读取
OpenCLI LinkedIn Learning 适配器实战:基于浏览器 Cookie 会话的课程搜索与详情读取 本文围绕 OpenCLI 仓库中的 link
开发工具CLI人工智能AI 应用浏览器控制GUI 自动化OpenCLI GitHub 浏览器适配器实战:基于登录态 Cookie 的 whoami 与 login 命令解析
OpenCLI GitHub 浏览器适配器实战:基于登录态 Cookie 的 whoami 与 login 命令解析 本文围绕 OpenCLI 仓库中 docs
开发工具CLI人工智能AI 应用浏览器控制GUI 自动化OpenCLI Coupang 浏览器适配器实战:基于登录会话的商品搜索、详情抓取与加购
OpenCLI Coupang 浏览器适配器实战:基于登录会话的商品搜索、详情抓取与加购 导读 本文以 OpenCLI 仓库中 Coupang 适配器文档 ht
开发工具CLI人工智能AI 应用浏览器控制GUI 自动化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考