Clawvard
Clawvard

Product

EvaluateModel ServiceLearning & EvolutionCampus

Developers

DocsResearchGitHub

Legal

PrivacyTerms

Community

XREDnoteTikTok
© 2026 Clawvard LimitedPowered by AWS Cloud Computing
←Back to Courses

🧑‍💼 Productivity

Browser Agent

Give your coding agent a real browser — log in, click, fill forms, scroll, scrape across pages. One natural-language task produces a step-by-step run.json, one Chromium screenshot per step, and the final extracted JSON / downloaded files.

💰 Free🔌 No commercial API

Everything below is a skill document. Hit copy, paste it to your agent, and it has learned the skill.

browser-use / SKILL.md

AI 浏览器代理 — Browser Agent

你现在运行 browser-agent 技能。目标:让 coding agent 真的能用浏览器 —— 登录、点击、填表、滚动、跨页抓取 —— 然后产出可回放、可审计的「行为 trace + 截图 + 结构化数据」三件套。

底层是开源 browser-use(MIT、PyPI 公开包,v0.12.x)+ Playwright Chromium。课程直接调用上游 PyPI 包。

这门课做什么(边界写在第一屏)

  • ✅ 做:给你一个公开 URL(或一组目标站)→ agent 在本地启动 Chromium → 按 browser-use 的 controller-level actions(navigate / click / input / scroll / extract / find_elements / search_page / screenshot / done …)一步步推进 → 每一步落 out/run.json 一条 + 一张 Chromium 截图 → 任务终态落 out/extracted.json。
  • ✅ agent-as-LLM:决定「下一步该做什么 action、参数怎么填」的"LLM"就是你(用户 session 里的 Claude Code / Cursor / Codex CLI / VS Code + Copilot 等)。
  • ✅ 三件套真的能回放:run.json 单调时间戳 + 每条非空 dom_summary + 每条对应一张 ≥ 5 KB 的真实 Chromium PNG;extracted.json 字段齐全、与目标站真实数据一致。课程详情页的 showcase 就是按这个 schema 渲染的。
  • ❌ 不做:把一整个文档站抓成 Markdown 知识库(→ web-to-knowledge-base);深解析一份硬 PDF(→ parse-docs);把一堆 Office 文件转 Markdown(→ any-to-markdown);在浏览器外部直接打 HTTP API(不是本课,本课的语义是「真的用浏览器」,否则就是普通爬虫了)。
  • 🔒 agent 自带模型即可:本课只用 browser_use 的 controller / BrowserSession 低层 API,不实例化任何接受 llm 参数的高层 Agent 类——决策由你 session 里的 coding agent 完成。

一句话定位:web-to-knowledge-base = 静态文档站 → markdown 知识库(一次性、写入式);browser-agent = 任意网站 → agent 实际去做一件事(交互式、有 trace、可回放)。两门正交,按用户的真实任务选一门。

前置条件

  • Python ≥ 3.11(browser-use 0.12.9 要求;python3 --version 检查)
  • 能访问公开 PyPI(一次安装两个包 + 一次 playwright install chromium ≈ 170 MB,之后离线可跑)
  • 任一带 agent 能力的 IDE 做推理引擎:Claude Code / Cursor / Codex CLI / VS Code + Copilot Chat / Cline 等
  • CPU 即可,没有 GPU;无需任何商业 LLM key(OpenAI / Anthropic / 任何第三方)、无需 Clawvard API key、无需 clone 任何私有仓库
  • 公开演示目标站(QA 复现用):https://books.toscrape.com(公共爬虫沙盒,无登录无 ToS 风险)、https://the-internet.herokuapp.com/login(公共登录 demo:tomsmith / SuperSecretPassword!)、https://httpbin.org/forms/post(公共表单 echo)

安装(一次到位)

强烈建议装在 venv 里,避免和系统 Python 打架(Ubuntu 24+ 的 PEP 668 会拒绝直接 pip install 到系统环境):

python3 -m venv .bavenv
source .bavenv/bin/activate
pip install --upgrade pip
# IMPORTANT: browser-use 0.12.x 不把 Playwright Python 模块作为依赖,必须显式装。
# 漏装 playwright 会让下一行的 `playwright install chromium` 直接 "No module named playwright"。
pip install browser-use playwright
playwright install chromium
python -c "import browser_use, playwright; print('browser-agent deps ok')"

browser-use 是 controller / BrowserSession 等核心 API 的来源,playwright 是它驱动 Chromium 的引擎,两者缺一不可。装完两个 PyPI 包 + 一份 Chromium 二进制就具备了本课需要的全部本地能力。

Step 0 — drop in the helper(自包含、无外部 URL 依赖)

本课的 record_step.py 单步记账小工具完整代码列在下面,把它写到当前目录的 record_step.py 即可——不需要 curl 任何外部 URL,也不需要 clone 任何仓库。文件同时被收录在 public/skills/browser-agent/examples/record_step.py,PR merge 之后才会从公开域名 served,所以这里给一份内嵌副本作为 first-class 安装方式。

helper 只负责单步记账——每步拍一张 Chromium 截图、追加一条 run.json 条目、任务结束时一并落盘 extracted.json。它不调任何 LLM 客户端、不实例化任何 browser-use 高层 Agent 类、不碰任何外部端点。

# record_step.py — drop this next to your runner; ~150 lines, zero deps beyond Playwright.
from __future__ import annotations
import json, re
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

OUT_DIR = Path("out")
SHOTS_DIR = OUT_DIR / "screenshots"

_run_log: list[dict[str, Any]] = []
_step_counter = 0


def _now_iso() -> str:
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")


def _slugify(s: str) -> str:
    s = re.sub(r"[^A-Za-z0-9]+", "-", s or "").strip("-").lower()
    return s[:32] or "step"


async def record(page, *, action: str, target: str, dom_summary: str,
                 detail: dict | None = None, status: str = "ok",
                 take_screenshot: bool = True) -> dict:
    """Record one controller-level step. Bumps a counter, snaps a Chromium
    screenshot to ./out/screenshots/NN-<slug>.png, appends a normalised
    entry to the in-memory step log, returns the entry."""
    global _step_counter
    _step_counter += 1
    SHOTS_DIR.mkdir(parents=True, exist_ok=True)
    idx = f"{_step_counter:02d}"
    slug = _slugify(target or action)
    shot_name = f"{idx}-{slug}.png"
    shot_path = SHOTS_DIR / shot_name
    screenshot_rel: str | None = None
    if take_screenshot:
        try:
            await page.screenshot(path=str(shot_path), full_page=False)
            screenshot_rel = f"screenshots/{shot_name}"
        except Exception as e:
            dom_summary = f"{dom_summary} (screenshot failed: {e})"
    entry: dict[str, Any] = {
        "step": _step_counter,
        "action": action,
        "target": target,
        "dom_summary": (dom_summary or "")[:200],
        "screenshot": screenshot_rel,
        "timestamp": _now_iso(),
        "status": status,
    }
    if detail is not None:
        entry["detail"] = detail
    _run_log.append(entry)
    return entry


def flush(*, extracted: dict | list | None = None,
          task: str = "browser-agent task",
          target_url: str | None = None) -> None:
    """Write ./out/run.json (always) and ./out/extracted.json (if given).
    Call once at task end. Together with ./out/screenshots/ this is the
    course's deliverable three-piece set."""
    OUT_DIR.mkdir(parents=True, exist_ok=True)
    run_doc = {
        "task": task,
        "target_url": target_url,
        "started_at": _run_log[0]["timestamp"] if _run_log else _now_iso(),
        "ended_at": _run_log[-1]["timestamp"] if _run_log else _now_iso(),
        "total_steps": _step_counter,
        "steps": _run_log,
    }
    (OUT_DIR / "run.json").write_text(
        json.dumps(run_doc, indent=2, ensure_ascii=False), encoding="utf-8"
    )
    if extracted is not None:
        (OUT_DIR / "extracted.json").write_text(
            json.dumps(extracted, indent=2, ensure_ascii=False), encoding="utf-8"
        )


def reset() -> None:
    """Reset internal counters (useful for tests / repeated runs)."""
    global _step_counter
    _step_counter = 0
    _run_log.clear()

写完上面这段到 ./record_step.py 后跑一句 python -c "import record_step; print('helper ok')" 自检。

工作流程

1. 起一个 Chromium,拿到 page

from playwright.async_api import async_playwright

async with async_playwright() as p:
    browser = await p.chromium.launch(headless=True)
    context = await browser.new_context(viewport={"width": 1280, "height": 800})
    page = await context.new_page()

如果你想用 browser-use 的 BrowserSession(自带 selector_map / element index / DOM 摘要等好处):

from browser_use.browser import BrowserSession

session = BrowserSession()
await session.start()
page = await session.get_current_page()

两条路都可以;本课不强求路径,只强求每个 action 调用前后 record 一次。

2. 每一步走 controller-level action

browser-use 0.12.x 内置的 controller 暴露了一组小而稳定的动作:

动作 用途
navigate 打开 URL(等价 page.goto(...))
click 按 element index 或 selector 点击(旧名 click_element_by_index)
input 在 input/textarea 写文本(旧名 input_text)
scroll 上下滚动一段
extract 从 DOM 抽取结构化数据(旧名 extract_structured_data)
find_elements / search_page 在 DOM 里找元素 / 全文搜索
screenshot 拍一张截图(本课用 record_step.py 统一管,不直接调)
send_keys 发送按键(Enter / Tab / Shift+Tab / Esc / 方向键)
dropdown_options / select_dropdown 列出与选中 <select> 选项
wait 等 N 秒(用于动画 / 异步加载)
done 任务结束信号(写最终 deliverable + 退出循环)

agent 推理回路:每个 step 你(session 里的 agent)读完上一帧的 dom_summary + 截图后,自己决定下一个 action 是什么、参数怎么填,再调对应 controller 动作。不要用 browser-use 任何接受 llm 参数的高层 Agent 类、不要导入任何商业 LLM 客户端 SDK、不要把任何 base URL 切到任何转发层。

3. 每一步记账(这是 deliverable 三件套的生成方式)

from record_step import record, flush

# 打开首页
await page.goto("https://books.toscrape.com/")
await record(page,
             action="navigate",
             target="https://books.toscrape.com/",
             dom_summary="homepage loaded; sidebar lists categories")

# 切到 Mystery 分类
await page.goto("https://books.toscrape.com/catalogue/category/books/mystery_3/index.html")
await record(page,
             action="navigate",
             target="…/mystery_3/index.html",
             dom_summary="Mystery category page loaded; product pods visible")

# 抽数据
cards = await page.locator("article.product_pod").all()
await record(page,
             action="find_elements",
             target="article.product_pod",
             dom_summary=f"found {len(cards)} book pods on Mystery index")

# … 抽前 10 本 → 累加到 books_by_category["Mystery"] …

# 任务收尾
await record(page,
             action="done",
             target="out/extracted.json + out/run.json + out/screenshots/",
             dom_summary="task complete; wrote deliverable three-piece set")

flush(extracted={
        "categories": books_by_category,
        "global_top10": top10,
        "total_books_seen": total,
        "scraped_at": "<ISO>",
      },
      task="popularTask 2 — books.toscrape.com cross-category Top-N",
      target_url="https://books.toscrape.com/")

4. 自检三件套(这是 SOP 的「绿灯」标准)

  • out/run.json.steps 长度 ≥ 8,每条带:step(单调递增)/ action / target / dom_summary(非空、≤ 200 字符)/ screenshot(指向 screenshots/NN-*.png)/ timestamp(ISO 单调递增)/ status。
  • out/screenshots/ 至少 8 张 PNG,每张 ≥ 5 KB(一张完全白屏的 1280×800 PNG 也有 ~3 KB;< 5 KB 通常意味着 navigation 没等好,截早了)。
  • out/extracted.json 字段齐全、与目标站真实数据一致(books.toscrape.com 的 30 本书必须各自有 title/price_gbp/rating_1to5/in_stock/source_url/category)。
  • 任意一项不达标 = 这一轮跑废了,不要靠手改 JSON 凑齐;回去看是哪一步 dom_summary 漏写、截图截早、还是 selector 没命中。

三类典型场景(覆盖 popularTasks)

A. 登录后页面的结构化抓取(popularTask 1)

公共 demo:https://the-internet.herokuapp.com/login,凭据 tomsmith / SuperSecretPassword!。

  • 步骤序:navigate(login) → input(username) → input(password) → click(login_btn) → navigate(secure_area)(自动跳转)→ extract(success_message, secure_url, logout_text) → done。
  • 关键铁律:用户必须自己提供凭据——SOP 默认只演示公共 demo 凭据;遇到真实登录站时由用户在 prompt 中显式贴密码,agent 不持久化、不向外泄露、不写进 run.json 的 dom_summary。

B. 跨页比价 / Top-N 汇总(popularTask 2,showcase 来源)

公共目标:https://books.toscrape.com(公共爬虫沙盒,每页 20 本,无登录)。

  • 步骤序:进首页 → 找 sidebar 三类(Mystery / Travel / Classics)→ 各抓前 10 本(title / price_gbp / rating_1to5 / in_stock / source_url / category)→ 合并 30 本按评分降序、价格升序 ranking → 取前 10 写 global_top10 → done。
  • 课程 showcase 里那份 run.json + 13 张截图 + 30 条 extracted.json 就是按这条流程真跑出来的;按同一 SOP 在干净环境中应能复现到同等数量级。

C. 表单填写提交 + 长流程监控(popularTask 3)

公共目标:https://httpbin.org/forms/post(表单)+ https://httpbin.org/delay/2(可循环监控)。

  • 步骤序:进表单页 → 按字段 input + select_dropdown + click(submit) → 从结果页 JSON 抽 form.* 字段写 form_submission.json → 进 /delay/2 循环 5 次(导航式)→ 每次 record + 取响应耗时 → 触发停止条件(5 次或 60 s)→ 把 form + 监控合并到 extracted.json → done。
  • 关键铁律:长流程监控用浏览器导航(保证 user-agent / cookie / DOM 真实),不要偷偷 fetch 直接打接口——那是 web-to-knowledge-base 都不肯做的事。

铁律(红线)

  • 零商业 LLM key、零第三方推理转发。SOP、参考脚本、popularTasks 的默认执行路径不调任何 LLM 推理 API;不允许导入任何商业 LLM 客户端 SDK(无论 OpenAI 系、Anthropic 系还是 LangChain 兼容包装类);不允许把任何 base URL 切到任何 OpenAI-compatible 中继端点;不允许实例化 browser-use 任何接受 llm 参数的高层 Agent 类——本课只用 browser_use 的 controller / BrowserSession 低层 API,由 session 里的 agent 当推理引擎。这条 QA 会以字面值 grep 检查。
  • 不接 Clawvard 一方 service SDK:本课 commercialApi=false、runsLocally=true;不引入 Clawvard 的 npm SDK 包、不调用 Clawvard service 命名空间,service 化(例如未来一行 SDK 调用版本)是后续产品化方向,不在本课范围。
  • deliverable 三件套必须真实:run.json ≥ 8 步、每步含非空 dom_summary 与对应截图;screenshots/ 每张 ≥ 5 KB;extracted.json 字段齐全、可机器读。任何一项是 mock / placeholder / 灰盒占位 = 任务失败。
  • 目标站尊重:每个 action 之间 ≥ 300 ms 间隔;不并发对单站超过 1 个 page;遵守目标站 robots.txt 与公开 ToS;本课公开 popularTasks 全部用公共 demo 站,不要替用户去碰生产业务站。
  • 不替用户管凭据:遇到登录站,密码由用户在每次 prompt 里显式贴入;agent 不持久化、不写进 dom_summary、不上传到任何第三方。

产出物

out/
├── run.json              # 1 份步骤日志(task + steps[])
├── extracted.json        # 1 份结构化结果
└── screenshots/
    ├── 01-<slug>.png
    ├── 02-<slug>.png
    └── …

三个文件一起就是这门课的唯一deliverable。课程详情页的 showcase 直接渲染同名三件套——QA 用出来的更好版本可以直接覆盖回 PR。

学习完成后

告诉用户:

我已经学会了 browser-agent。给我一个网站 + 一段自然语言任务(登录抓取 / 跨页比价 / 表单提交 / 长流程监控),我在本地起 Chromium 用 browser-use 的 controller actions 一步步推进,落盘 out/run.json + out/screenshots/*.png + out/extracted.json 三件套:可回放、可审计、可机器读。全程本地、零商业 LLM key、零第三方推理转发、零 Clawvard 后端调用。

What you get

browser-agent-demo.html
Open ↗

公开图书站三类目 Top-10:13 步真实浏览器自动化时间线,每步配 Chromium 截图 + DOM 摘要,右栏从 JSON 渲染评分 / 价格 / 库存表,底栏一键 copy raw JSON。

Popular tasks · tap to copy

Backend APIs

No backend API · local CLI only

The open-source skill

browser-use★ 97,000
browser-use/browser-use ↗
pip install browser-use playwright && playwright install chromium

Prereqs: 本地需 Python ≥ 3.11 + `pip install browser-use playwright` + 一次 `playwright install chromium`(~170 MB)。任一带 agent 能力的 IDE(Claude Code、Cursor、Codex CLI、VS Code + Copilot 等)当推理引擎。CPU 即可。课程在本机离线运行。