webcli
Secure, agent-driven web data extraction.
Turn any website into structured data. No browser required.
Quick Start • Adapters • MCP Server • Architecture • Security
______________________________________________________________________
什么是webcli?
webcli使用 API第一种方法 --在接触浏览器之前,它会尝试公共API、RSS提要和结构化HTML。专为需要阅读网络的AI代理而构建。
与opencli相比:
| opencli | webcli | |
|---|---|---|
| 浏览器 | 重用您的Chrome会话 | 大多数网站不需要浏览器 |
| 反侦测 | 补丁navigator.webdriver,伪造指纹 | 诚实的自动化,没有逃避 |
| 扩展 | 上帝模式Chrome扩展程序(调试器+Cookie+所有URL) | 根本没有扩展程序 |
| 安全 | 浏览器上下文中的任意JS | 沙盒V8隔离,域锁定获取 |
| 代理接口 | 仅限CLI | CLI+MCP服务器 |
| 认证 | 窃取您的cookie | 您明确提供API密钥 |
快速开始
# Clone and install
git clone https://github.com/ashark-ai-05/webcli.git
cd webcli
npm install
# List available adapters
npx tsx src/main.ts list
# Search Hacker News
npx tsx src/main.ts run hackernews search -a query=AI -a limit=5
# Get live crypto prices
npx tsx src/main.ts run coingecko prices -a coins=bitcoin,ethereum,solana
# Search Bluesky users
npx tsx src/main.ts run bluesky search -a query=typescript -a limit=5内置适配器
黑客新闻
# Search stories
webcli run hackernews search -a query=rust -a limit=10
# Output as JSON (for piping to other tools)
webcli run hackernews search -a query=rust -f json
# Output as CSV (for spreadsheets)
webcli run hackernews search -a query=rust -f csvCoinGecko
# Live prices
webcli run coingecko prices -a coins=bitcoin,ethereum,solana
# Trending coins
webcli run coingecko trending -a limit=10蓝天
# Search users
webcli run bluesky search -a query=developer -a limit=5
# Get a profile
webcli run bluesky profile -a handle=bsky.appMCP服务器
webcli作为一个 主控程序 服务器,以便AI代理(Claude、Cursor等)可以将其用作工具。
# Start MCP server
npx tsx src/main.ts --mcp添加到您的Claude Code MCP配置中:
{
"mcpServers": {
"webcli": {
"command": "npx",
"args": ["tsx", "/path/to/webcli/src/main.ts", "--mcp"]
}
}
}可用的MCP工具:
| 工具 | 说明 |
|---|---|
webcli_run | 运行任何适配器--从网站提取数据 |
webcli_list | 列出所有可用适配器 |
webcli_schema | 获取适配器的数据模式(字段名、类型、角色) |
代理可以发现站点提供的数据(webcli_schema),然后提取它(webcli_run)--所有这些都没有对网站的任何硬编码知识。
YAML适配器DSL
每个数据源都被定义为一个声明性的YAML适配器。以下是CoinGecko价格适配器:
site: coingecko
name: prices
description: Live cryptocurrency prices
version: 1
source:
type: api
base_url: https://api.coingecko.com/api/v3
auth: none
rate_limit: { requests: 30, per: 60 }
args:
coins: { type: string, default: "bitcoin,ethereum" }
currency: { type: string, default: usd }
schema:
type: price_feed
entity: cryptocurrency
fields:
id: { role: id }
price: { role: value, unit: currency }
change_24h: { role: delta }
market_cap: { role: metric }
update_frequency: "~60s"
pipeline:
- fetch:
url: /simple/price
params:
ids: "${{ args.coins }}"
vs_currencies: "${{ args.currency }}"
include_market_cap: true
include_24hr_change: true
- transform: |
Object.entries(data).map(([id, v]) => ({
id, price: v[args.currency],
change_24h: v[args.currency + '_24h_change'].toFixed(2) + '%',
market_cap: v[args.currency + '_market_cap']
}))
columns: [id, price, change_24h, market_cap]管道步骤
| 步骤 | 目的 | 示例 |
|---|---|---|
fetch | HTTP请求 | fetch: { url: /api/data, params: { q: "${{ args.query }}" } } |
select | 提取嵌套密钥 | select: response.data.items |
transform | 沙盒V8中的JS | transform: "data.map(x => ({ ...x, rank: x.score * 2 }))" |
map | 重塑每个项目 | map: { title: "${{ item.name }}", score: "${{ item.points }}" } |
filter | 保持匹配项目 | filter: "item.score > 10" |
sort | 订单结果 | sort: { field: score, order: desc } |
limit | 上限结果计数 | limit: "${{ args.limit }}" |
dedupe | 删除重复项 | dedupe: id |
flatten | 扁平嵌套数组 | flatten: tags |
建筑
┌─────────┐ ┌────────────┐
│ CLI │ │ MCP Server │
└────┬────┘ └─────┬──────┘
└───────┬──────┘
v
┌────────────────────────┐
│ Core Engine │
│ Pipeline Executor │
│ Adapter Registry │
│ Rate Limiter │
└───────────┬────────────┘
v
┌─────────────────────────────────┐
│ Extractor Cascade │
│ HTTP/API > RSS > HTML > Browser│
└─────────────────────────────────┘
v
┌─────────────────────────────────┐
│ Discovery Engine │
│ Schema Inference │
│ Known Site Registry (8 sites) │
│ Field Role Detection │
└─────────────────────────────────┘
v
┌─────────────────────────────────┐
│ Data Layer │
│ Snapshot Store + Diff Engine │
│ Subscription Manager │
│ Adaptive Interval Scheduler │
└─────────────────────────────────┘提取器级联
webcli首先尝试了最轻的提取方法:
- HTTP/API --直接调用JSON API。没有浏览器。最快的。
- RSS/Atom --源解析。非常适合新闻网站。
- 超文本标记语言 --JSON-LD、结构化数据、DOM模式检测。
- 浏览器 --剧作家(沙盒)。SPA的最后手段。
90%的有用数据无需浏览器即可访问。
Discovery发动机
将webcli指向任何URL,它就会计算出数据模型:
- 已知站点注册表 --8个具有预映射API的主要网站(CoinGecko、HN、Bluesky、Reddit、StackOverflow、GitHub、X、维基百科)
- 模式推断 --从字段名称和值中检测字段角色(id、标题、url、时间戳、分数、价格、作者)
- 实体打字 --将数据分类为文章、帖子、价格、用户等。
安全
webcli被设计为opencli等工具的安全替代品。每一层都有明确的安全边界:
沙盒表达式
这 ${{ }} 模板引擎和 transform 跨步磨合 独立的V8上下文 通过 vm.createContext:
Available: args, item, index, data, Math, Date, JSON, String, Array, Object
BLOCKED: fetch, require, import, process, globalThis, eval, Function,
setTimeout, Buffer, fs, child_process内存限制:64MB。时间限制:转换5秒,表达式1秒。
域锁定获取
这 fetch 管道步骤仅向与适配器声明的URL匹配的URL发出请求 source.base_url.CoinGecko适配器无法向Twitter的API发出请求。
适配器验证
每个适配器在执行前都经过验证:
- 最多20个管道步骤
- 只允许已知的步骤类型
- 源类型和身份验证方法必须来自允许的列表
- 管道中任何地方都没有shell命令
速率限制
全局和每个站点的令牌桶速率限制可防止意外DoS:
rate_limits:
global: { max_requests_per_minute: 120 }
per_site:
default: { max_requests_per_minute: 30 }
overrides:
api.coingecko.com: 50诚实自动化
无反检测。没有伪造指纹。不 navigator.webdriver 修补。webcli诚实地表明了自己的身份:
User-Agent: webcli/0.1.0 (+https://github.com/webcli)如果一个网站屏蔽了我们,我们会优雅地升级(尝试浏览器,然后进行身份验证,然后报告被屏蔽)——我们不会开始逃避军备竞赛。
输出格式
# Pretty table (default)
webcli run hackernews search -a query=AI
# JSON (for piping to jq, agents, scripts)
webcli run hackernews search -a query=AI -f json
# CSV (for spreadsheets, pandas)
webcli run hackernews search -a query=AI -f csv数据层
快照和差异
webcli可以跟踪随时间的变化:
// Snapshot store saves results to ~/.webcli/data/{site}/{name}/
// Diff engine compares snapshots to detect added/removed/changed items
{
"added": [{ "id": "solana", "price": 142.50 }],
"removed": [],
"changed": [{
"id": "bitcoin",
"fields": { "price": { "old": 71000, "new": 71250 } }
}],
"unchanged_count": 1
}自适应轮询
订阅会自动调整其轮询频率:
- 高波动性 (>50%的数据发生了变化)--将间隔减半
- 适度活动 (10-50%变化)——保持当前间隔
- 无变化 --间隔增加50%
尊重 min_interval 和 max_interval 边界,加 update_frequency 来自适配器模式的提示。
发展
# Run tests
npm test
# Watch mode
npm run test:watch
# Type check
npm run lint
# Run the CLI in dev mode
npm run dev -- list项目结构
webcli/
src/
core/ # Pipeline engine, types, adapter system
extractors/ # HTTP, RSS, HTML, cascade
discovery/ # Schema inference, known sites
data/ # Snapshots, diffs, subscriptions
scheduler/ # Adaptive intervals
interfaces/ # CLI (commander) + MCP server
utils/ # Config, logging
adapters/ # Built-in YAML adapters
tests/e2e/ # End-to-end tests (hit live APIs)编写自定义适配器
在中创建一个YAML文件 ~/.webcli/adapters/{site}/{name}.yaml:
site: mysite
name: feed
description: My custom feed
version: 1
created_by: manual
source:
type: api
base_url: https://api.mysite.com
auth: none
args:
limit: { type: number, default: 10 }
schema:
type: feed
entity: article
fields:
title: { role: title }
url: { role: url }
pipeline:
- fetch: { url: /posts, params: { limit: "${{ args.limit }}" } }
- select: data
- map:
title: "${{ item.title }}"
url: "${{ item.url }}"
date: "${{ item.published_at }}"
- limit: "${{ args.limit }}"
columns: [title, url, date]验证它:
webcli validate ~/.webcli/adapters/mysite/feed.yaml然后使用它:
webcli run mysite feed -a limit=5许可证
阿帕奇-2.0
