162 lines
9.5 KiB
Markdown
162 lines
9.5 KiB
Markdown
---
|
||
id: 2026-03-18-opencli-research
|
||
title: OpenCLI 深度研究:把任何网站变成 CLI
|
||
slug: opencli-research
|
||
status: inbox
|
||
content_type: article
|
||
language: zh-CN
|
||
source_urls:
|
||
- https://github.com/jackwener/opencli
|
||
tags:
|
||
- cli-tool
|
||
- browser-automation
|
||
- ai-agent
|
||
- web-scraping
|
||
- open-source
|
||
created_at: 2026-03-18T00:00:00+08:00
|
||
updated_at: 2026-03-18T00:00:00+08:00
|
||
---
|
||
|
||
# OpenCLI 深度研究:把任何网站变成 CLI
|
||
|
||
> Make any website your CLI. Zero risk · Reuse Chrome login · AI-powered discovery
|
||
|
||
## 项目信息
|
||
|
||
- 仓库: git@github.com:jackwener/opencli.git
|
||
- npm: @jackwener/opencli
|
||
- 协议: BSD-3-Clause
|
||
- Node.js >= 18
|
||
|
||
## 核心定位
|
||
|
||
把任何网站变成命令行工具——复用 Chrome 登录态,零风险,AI 驱动自动发现 API。
|
||
|
||
## 架构总览
|
||
|
||
```
|
||
┌────────────────────────────────────────────────────────────────────────┐
|
||
│ opencli CLI (main.ts) │
|
||
│ Commander.js 命令树 │
|
||
├──────────┬─────────────┬──────────────┬───────────────────────────────┤
|
||
│ 内置命令 │ 动态站点命令 │ AI Agent 命令 │ 管理命令 │
|
||
│ list │ bilibili/* │ explore │ validate / verify │
|
||
│ doctor │ twitter/* │ synthesize │ setup │
|
||
│ setup │ zhihu/* │ generate │ │
|
||
│ │ ...18 sites │ cascade │ │
|
||
├──────────┴─────────────┴──────────────┴───────────────────────────────┤
|
||
│ │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ Engine │ │ Registry │ │ Output │ │
|
||
│ │ (engine.ts) │────▶│ (registry.ts) │────▶│ (output.ts) │ │
|
||
│ │ │ │ │ │ │ │
|
||
│ │ • Manifest快速路径│ │ • cli() 注册函数 │ │ • table (默认) │ │
|
||
│ │ • FS扫描回退 │ │ • Map<key,Cmd> │ │ • json / yaml │ │
|
||
│ │ • YAML 自动解析 │ │ • Strategy enum │ │ • markdown / csv│ │
|
||
│ │ • TS 惰性加载 │ │ • Arg 接口 │ │ │ │
|
||
│ └────────┬────────┘ └─────────────────┘ └─────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────▼────────┐ ┌─────────────────┐ │
|
||
│ │ Pipeline │ │ Browser │ │
|
||
│ │ (pipeline/) │ │ (browser.ts) │ │
|
||
│ │ │ │ │ │
|
||
│ │ YAML 声明式引擎 │◀───▶│ PlaywrightMCP │ │
|
||
│ │ 14 种 Step │ │ JSON-RPC ↔ Chrome│ │
|
||
│ │ 模板表达式 │ │ Page 抽象层 │ │
|
||
│ └─────────────────┘ └─────────────────┘ │
|
||
└────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
## 核心设计 1:双引擎
|
||
|
||
YAML 声明式 + TypeScript 编程式双引擎,共享同一个 Registry 和 Browser 抽象层。
|
||
|
||
数据结构 CliCommand 的 func 和 pipeline 二选一——消除引擎切换的特殊情况处理。
|
||
|
||
- YAML: src/clis/<site>/<name>.yaml,14 种 Pipeline Step,放入即自动注册
|
||
- TS: src/clis/<site>/<name>.ts,通过 cli() 函数注册,首次执行时才惰性加载
|
||
- 发现机制: cli-manifest.json 快速路径 + FS scan 回退(生产零开销 + 开发热加载)
|
||
|
||
Pipeline 步骤:
|
||
- 数据获取: navigate, fetch, evaluate, snapshot, intercept, tap
|
||
- 数据变换: select, map, filter, sort, limit
|
||
- UI 操作: click, type, wait, press
|
||
- 模板语法: \${{ item.field }}, \${{ args.limit }}, \${{ index + 1 }}
|
||
|
||
## 核心设计 2:5 级认证策略
|
||
|
||
```
|
||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||
│ PUBLIC │───▶│ COOKIE │───▶│ HEADER │───▶│INTERCEPT │───▶│ UI │
|
||
│ Tier 1 │ │ Tier 2 │ │ Tier 3 │ │ Tier 4 │ │ Tier 5 │
|
||
│ ~1s ⚡ │ │ ~7s 🔄 │ │ ~7s 🔄 │ │ ~10s 🔄 │ │ ~15s+ 🐌│
|
||
├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤
|
||
│HackerNews│ │ Bilibili │ │ Twitter │ │ 小红书 │ │ 遗留站点 │
|
||
│ V2EX/BBC │ │ Zhihu │ │ GraphQL │ │ Pinia+ │ │ │
|
||
│ GitHub │ │ Reddit │ │ │ │ XHR Hook │ │ │
|
||
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||
```
|
||
|
||
cascade 命令自动逐级探测:对目标 URL 依次尝试 PUBLIC → COOKIE → HEADER,第一个成功的就是最佳策略。
|
||
|
||
## 核心设计 3:AI 自动发现
|
||
|
||
```
|
||
explore <url> → 导航 + 自动滚动 + fuzzing + 网络捕获 + 框架检测 + 端点评分 + 能力推理
|
||
synthesize <site> → 从 explore 产物生成 YAML 候选
|
||
generate <url> → explore + synthesize + register 一键完成
|
||
```
|
||
|
||
端点评分系统: JSON +10, API路径 +3, 搜索参数 +3, 分页 +2, 有数据 +5, 空数据 -3(反爬检测)。阈值 ≥5 才保留。
|
||
|
||
## 核心设计 4:拦截器系统
|
||
|
||
三种拦截模式:
|
||
- 全局拦截: installInterceptor() — 持久 monkey-patch,累积捕获
|
||
- 读取+清空: getInterceptedRequests() — 读取后清空
|
||
- tap 拦截: 临时拦截 + Promise 等待 + 自动恢复原函数
|
||
|
||
tap 步骤是最精妙的设计——不自己构造签名,而是调用目标站点的 Pinia/Vuex Store Action,让前端框架自己完成鉴权,再拦截网络响应取数据。「用敌人的武器打败敌人」。
|
||
|
||
## 浏览器层
|
||
|
||
通过 Playwright MCP Bridge Chrome 扩展连接用户已登录的浏览器——不启动新浏览器实例,复用用户的 Cookie/Session/登录态。这是「零风险」的核心保障。
|
||
|
||
Page 抽象层 (IPage): goto, evaluate, snapshot, click, autoScroll, installInterceptor, getInterceptedRequests
|
||
|
||
## 支持站点(18 个,100+ 命令)
|
||
|
||
Public(无需浏览器): hackernews, bbc, github, v2ex(部分)
|
||
|
||
Browser(需 Chrome 登录):
|
||
- bilibili (11 cmds): hot, search, me, favorite, history, feed, subtitle, dynamic, ranking, following, user-videos
|
||
- twitter (17 cmds!): trending, bookmarks, profile, search, timeline, following, followers, notifications, post, reply, delete, like, article, follow, unfollow, bookmark, unbookmark
|
||
- zhihu (3), xiaohongshu (5), xueqiu (6), reddit (4), weibo, boss, coupang, youtube, yahoo-finance, reuters, smzdm, ctrip, v2ex(部分)
|
||
|
||
## 技术栈
|
||
|
||
CLI: Commander.js | 浏览器: Playwright MCP Bridge | YAML: js-yaml | 输出: cli-table3 + chalk | 构建: TypeScript | 测试: Vitest (~52 E2E) | 运行时: Node.js >= 18
|
||
|
||
## 架构亮点
|
||
|
||
1. CliCommand 的 func/pipeline 二选一——消除引擎切换 if/else,Good Taste
|
||
2. Manifest 快速路径 + FS scan 回退——零开销启动 + 无缝开发
|
||
3. 5 级策略 + cascade 自动探测——认证复杂度分层管理
|
||
4. tap 步骤(Store Action Bridge)——用框架自己的能力绕过签名
|
||
5. Page 抽象层 (IPage)——浏览器操作解耦,方便测试 mock
|
||
6. explore 端点评分——把 AI 发现从「试错」降为「打分排序」
|
||
|
||
## 潜在问题
|
||
|
||
- Twitter Bearer Token 硬编码(轮换风险)
|
||
- evaluate 步骤 JS 注入用字符串拼接(XSS 向量,虽运行在用户自己浏览器)
|
||
- 无重试机制(网络抖动直接失败)
|
||
- E2E 测试依赖真实站点(站点改版易失败)
|
||
|
||
## 选题角度思考
|
||
|
||
- 「把任何网站变成 CLI」的产品思路——从 API wrapper 到 AI 自动发现的演进
|
||
- 双引擎设计的 Good Taste——YAML 声明式 vs TS 编程式的边界在哪里
|
||
- 5 级认证策略——Web 反爬对抗的分层哲学
|
||
- tap 步骤的精妙设计——用前端框架自己的能力打败它
|
||
- 对 AI Agent 工具生态的启示——explore + synthesize + cascade 三件套 |