🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://skills.sh/aradotso/trending-skills/opencli-web-automation

💡 提示:需要 Node.js 和 NPM

OpenCLI 网页自动化 (OpenCLI Web Automation)

技能来自 ara.so — Daily 2026 Skills 合集

OpenCLI 通过复用 Chrome 已登录的浏览器会话,将任何网站转换为命令行界面。它开箱即用地支持 19 个站点和 80 多个命令,并允许您通过将 TypeScript 或 YAML 文件放入 clis/ 文件夹来添加新的适配器。


安装 (Installation)

# 通过 npm 全局安装 (Install globally via npm)
npm install -g @jackwener/opencli

# 一次性设置:发现 Playwright MCP 令牌并分发到所有工具
# (One-time setup: discovers Playwright MCP token and distributes to all tools)
opencli setup

# 验证一切正常 (Verify everything is working)
opencli doctor --live

前提条件 (Prerequisites)

  • Node.js >= 18.0.0
  • Chrome 浏览器正在运行并登录到目标网站 (running and logged into the target site)
  • Chrome 中已安装 Playwright MCP Bridge 扩展程序

从源码安装(开发)(Install from Source – Development)

git clone git@github.com:jackwener/opencli.git
cd opencli
npm install
npm run build
npm link

环境配置 (Environment Configuration)

# 必需:在运行 opencli setup 后,在 ~/.zshrc 或 ~/.bashrc 中设置
# (Required: set in ~/.zshrc or ~/.bashrc after running opencli setup)
export PLAYWRIGHT_MCP_EXTENSION_TOKEN="<your-token-from-setup>"

MCP 客户端配置(Claude/Cursor/Codex ~/.config/*/config.json)(MCP client config – Claude/Cursor/Codex ~/.config/*/config.json):

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp@latest", "--extension"],
      "env": {
        "PLAYWRIGHT_MCP_EXTENSION_TOKEN": "$PLAYWRIGHT_MCP_EXTENSION_TOKEN"
      }
    }
  }
}

关键 CLI 命令 (Key CLI Commands)

发现与注册表 (Discovery & Registry)

opencli list                        # 显示所有已注册的命令 (Show all registered commands)
opencli list -f yaml                # 以 YAML 格式输出注册表 (Output registry as YAML)
opencli list -f json                # 以 JSON 格式输出注册表 (Output registry as JSON)

运行内置命令 (Running Built-in Commands)

# 公共 API 命令(无需浏览器登录)(Public API commands - no browser login needed)
opencli hackernews top --limit 10
opencli github search "playwright automation"
opencli bbc news

# 浏览器命令(必须在 Chrome 中登录网站)(Browser commands - must be logged into site in Chrome)
opencli bilibili hot --limit 5
opencli twitter trending
opencli zhihu hot -f json
opencli reddit frontpage --limit 20
opencli xiaohongshu search "TypeScript"
opencli youtube search "browser automation"
opencli linkedin search "senior engineer"

输出格式 (Output Formats)

所有命令都支持 --format / -f

opencli bilibili hot -f table     # 丰富的终端表格(默认)(Rich terminal table - default)
opencli bilibili hot -f json      # JSON(可管道到 jq)(JSON - pipe to jq)
opencli bilibili hot -f yaml      # YAML
opencli bilibili hot -f md        # Markdown
opencli bilibili hot -f csv       # CSV 导出 (CSV export)
opencli bilibili hot -v           # 详细模式:显示管道调试步骤 (Verbose: show pipeline debug steps)

AI 智能体工作流(创建新命令)(AI Agent Workflow – Creating New Commands)

# 1. 深度探索一个网站 — 发现 API、认证、功能 (Deep explore a site — discovers APIs, auth, capabilities)
opencli explore https://example.com --site mysite

# 2. 从探索工件合成 YAML 适配器 (Synthesize YAML adapters from explore artifacts)
opencli synthesize mysite

# 3. 一步到位:探索 → 合成 → 注册 (One-shot: explore → synthesize → register in one command)
opencli generate https://example.com --goal "hot posts"

# 4. 策略级联 — 自动探测 PUBLIC → COOKIE → HEADER 认证
# (Strategy cascade — auto-probes PUBLIC → COOKIE → HEADER auth)
opencli cascade https://api.example.com/data

探索工件保存到 .opencli/explore/<site>/

  • manifest.json — 站点元数据 (site metadata)
  • endpoints.json — 发现的 API 端点 (discovered API endpoints)
  • capabilities.json — 推断的命令功能 (inferred command capabilities)
  • auth.json — 认证策略 (authentication strategy)

添加新适配器 (Adding a New Adapter)

选项 1:YAML 声明式适配器 (Option 1: YAML Declarative Adapter)

将一个 .yaml 文件放入 clis/ — 下次运行时自动注册:

# clis/producthunt.yaml
site: producthunt
commands:
  - name: trending
    description: 获取 Product Hunt 上的热门产品 (Get trending products on Product Hunt)
    args:
      - name: limit
        type: number
        default: 10
    pipeline:
      - type: navigate
        url: https://www.producthunt.com
      - type: waitFor
        selector: "[data-test='post-item']"
      - type: extract
        selector: "[data-test='post-item']"
        fields:
          name:
            selector: "h3"
            type: text
          tagline:
            selector: "p"
            type: text
          votes:
            selector: "[data-test='vote-button']"
            type: text
          url:
            selector: "a"
            attr: href
      - type: limit
        count: "{{limit}}"

选项 2:TypeScript 适配器 (Option 2: TypeScript Adapter)

// clis/producthunt.ts
import type { CLIAdapter } from "../src/types";

const adapter: CLIAdapter = {
  site: "producthunt",
  commands: [
    {
      name: "trending",
      description: "获取 Product Hunt 上的热门产品 (Get trending products on Product Hunt)",
      options: [
        {
          flags: "--limit <n>",
          description: "结果数量 (Number of results)",
          defaultValue: "10",
        },
      ],
      async run(options, browser) {
        const page = await browser.currentPage();
        await page.goto("https://www.producthunt.com");
        await page.waitForSelector("[data-test='post-item']");

        const products = await page.evaluate(() => {
          return Array.from(
            document.querySelectorAll("[data-test='post-item']")
          ).map((el) => ({
            name: el.querySelector("h3")?.textContent?.trim() ?? "",
            tagline: el.querySelector("p")?.textContent?.trim() ?? "",
            votes:
              el
                .querySelector("[data-test='vote-button']")
                ?.textContent?.trim() ?? "",
            url:
              (el.querySelector("a") as HTMLAnchorElement)?.href ?? "",
          }));
        });

        return products.slice(0, Number(options.limit));
      },
    },
  ],
};

export default adapter;

常见模式 (Common Patterns)

模式:认证的 API 提取(Cookie 注入)(Pattern: Authenticated API Extraction – Cookie Injection)

// 当站点公开 JSON API 但需要登录 cookie 时 (When a site exposes a JSON API but requires login cookies)
async run(options, browser) {
  const page = await browser.currentPage();

  // 先导航以确保 cookie 处于活动状态 (Navigate first to ensure cookies are active)
  await page.goto("https://api.example.com");

  const data = await page.evaluate(async () => {
    const res = await fetch("/api/v1/feed?limit=20", {
      credentials: "include", // 重用浏览器 cookie (reuse browser cookies)
    });
    return res.json();
  });

  return data.items;
}

模式:Header 令牌提取 (Pattern: Header Token Extraction)

// 从浏览器存储中提取认证令牌用于 API 调用 (Extract auth tokens from browser storage for API calls)
async run(options, browser) {
  const page = await browser.currentPage();
  await page.goto("https://example.com");

  const token = await page.evaluate(() => {
    return localStorage.getItem("auth_token") ||
           sessionStorage.getItem("token");
  });

  const data = await page.evaluate(async (tok) => {
    const res = await fetch("/api/data", {
      headers: { Authorization: `Bearer ${tok}` },
    });
    return res.json();
  }, token);

  return data;
}

模式:带等待的 DOM 抓取 (Pattern: DOM Scraping with Wait)

async run(options, browser) {
  const page = await browser.currentPage();
  await page.goto("https://news.ycombinator.com");

  // 等待动态内容加载 (Wait for dynamic content to load)
  await page.waitForSelector(".athing", { timeout: 10000 });

  return page.evaluate((limit) => {
    return Array.from(document.querySelectorAll(".athing"))
      .slice(0, limit)
      .map((row) => ({
        title: row.querySelector(".titleline a")?.textContent?.trim(),
        url: (row.querySelector(".titleline a") as HTMLAnchorElement)?.href,
        score:
          row.nextElementSibling
            ?.querySelector(".score")
            ?.textContent?.trim() ?? "0",
      }));
  }, Number(options.limit));
}

模式:分页 (Pattern: Pagination)

async run(options, browser) {
  const page = await browser.currentPage();
  const results = [];
  let pageNum = 1;

  while (results.length < Number(options.limit)) {
    await page.goto(`https://example.com/posts?page=${pageNum}`);
    await page.waitForSelector(".post-item");

    const items = await page.evaluate(() =>
      Array.from(document.querySelectorAll(".post-item")).map((el) => ({
        title: el.querySelector("h2")?.textContent?.trim(),
        url: (el.querySelector("a") as HTMLAnchorElement)?.href,
      }))
    );

    if (items.length === 0) break;
    results.push(...items);
    pageNum++;
  }

  return results.slice(0, Number(options.limit));
}

维护命令 (Maintenance Commands)

# 诊断所有工具的令牌和配置 (Diagnose token and config across all tools)
opencli doctor

# 测试实时浏览器连接 (Test live browser connectivity)
opencli doctor --live

# 交互式修复不匹配的配置 (Fix mismatched configs interactively)
opencli doctor --fix

# 非交互式修复所有配置 (Fix all configs non-interactively)
opencli doctor --fix -y

测试 (Testing)

npm run build

# 运行所有测试 (Run all tests)
npx vitest run

# 仅单元测试 (Unit tests only)
npx vitest run src/

# 仅端到端测试 (E2E tests only)
npx vitest run tests/e2e/

# CI 的无头浏览器模式 (Headless browser mode for CI)
OPENCLI_HEADLESS=1 npx vitest run tests/e2e/

故障排除 (Troubleshooting)

症状 (Symptom) 修复 (Fix)
Failed to connect to Playwright MCP Bridge 确保扩展程序已在 Chrome 中启用;安装后重启 Chrome (Ensure extension is enabled in Chrome; restart Chrome after install)
空数据 / Unauthorized (Empty data / Unauthorized) 打开 Chrome,导航到网站,登录或刷新页面 (Open Chrome, navigate to the site, log in or refresh the page)
Node API 错误 (Node API errors) 升级到 Node.js >= 18 (Upgrade to Node.js >= 18)
找不到令牌 (Token not found) 运行 opencli setupopencli doctor --fix
登录会话过期 (Stale login session) 在 Chrome 中访问目标网站并与之交互,以证明人为存在 (Visit the target site in Chrome and interact with it to prove human presence)

调试详细模式 (Debug Verbose Mode)

# 查看完整的管道执行步骤 (See full pipeline execution steps)
opencli bilibili hot -v

# 检查探索发现的内容 (Check what explore discovered)
cat .opencli/explore/mysite/endpoints.json
cat .opencli/explore/mysite/auth.json

项目结构(供适配器作者参考)(Project Structure – for Adapter Authors)

opencli/
├── clis/               # 将 .ts 或 .yaml 适配器放入此文件夹(自动注册)(Drop .ts or .yaml adapters here - auto-registered)
│   ├── bilibili.ts
│   ├── twitter.ts
│   └── hackernews.yaml
├── src/
│   ├── types.ts        # CLIAdapter、Command 接口 (CLIAdapter, Command interfaces)
│   ├── browser.ts      # Playwright MCP 桥接包装器 (Playwright MCP bridge wrapper)
│   ├── loader.ts       # 动态适配器加载器 (Dynamic adapter loader)
│   └── output.ts       # table/json/yaml/md/csv 格式化器 (table/json/yaml/md/csv formatters)
├── tests/
│   └── e2e/            # 每个站点的端到端测试 (E2E tests per site)
└── CLI-EXPLORER.md     # 完整的 AI 智能体探索工作流 (Full AI agent exploration workflow)

📄 原始文档

完整文档(英文):

https://skills.sh/aradotso/trending-skills/opencli-web-automation

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。