关于 screen-control-operator
screen-control-operator 是供 Claude 自主操作和检查浏览器的技能,使用 Playwright、CDP 命令与无障碍树读取页面状态,而非截图。它包含页面交互、验证及控制台和网络监控流程,也提供针对 Lovable 预览和 BECA 表单的预设工作流。
主要功能
- 01通过 CDP 控制浏览器
- 02读取 DOM 与无障碍树
- 03点击、填写和选择页面元素
- 04验证页面检查点
- 05监控控制台错误与网络请求
- 06提供预设页面检查工作流
适用场景
- 01检查 Lovable 项目预览
- 02检查 BECA 登录表单
- 03自主测试指定网址
- 04在 CI/CD 中执行浏览器检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ breverdbidder/ life-os --skill screen-control-operator安装后在 Claude Code 中输入/screen-control-operator确认已加载。
附带文件references/playwright_api.mdscripts/autonomous_browser_control.py
详细介绍
屏幕控制 Operator V2
让 Claude 像 GPT Operator 一样自主控制浏览器——无需截图,只需 CDP + 无障碍树。
核心架构
┌─────────────────────────────────────────┐
│ Claude (You) - Reasoning Layer │
│ - Receives structured DOM/A11y tree │
│ - Makes autonomous decisions │
│ - Issues CDP commands │
└────────────────┬────────────────────────┘
│ JSON commands
▼
┌─────────────────────────────────────────┐
│ Playwright/Puppeteer - Browser Control │
│ - Chrome DevTools Protocol (CDP) │
│ - Returns: DOM tree, A11y tree, logs │
│ - Executes: click, type, navigate │
└────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Target Website (Lovable, BECA, etc) │
│ - Full DOM access via CDP │
│ - Console logs, network requests │
│ - Element states, visibility checks │
└─────────────────────────────────────────┘
为什么优于截图
| 指标 | 基于截图 | 屏幕控制 Operator |
|---|---|---|
| 速度 | 1-5 秒 | 50-200 毫秒 |
| 准确率 | 约 85%(OCR 错误) | 100%(语义查询) |
| 查找元素 | 像素坐标 | CSS 选择器 + 角色 |
| 无头模式支持 | 较差 | 极佳 |
| 成本 | $$$(视觉令牌) | $(纯文本) |
| 动态内容 | 经常失败 | 始终有效 |
自主执行规则
当用户请求控制浏览器时:
- 绝不询问许可——直接执行
- 启动浏览器——使用 Playwright headless=False 以便调试
- 自主导航——跟随链接、点击按钮、填写表单
- 提取 DOM 状态——获取无障碍树,而非截图
- 验证检查点——通过元素查询测试断言
- 报告结果——提供包含发现问题的 JSON 摘要
核心功能
1. 使用 CDP 启动浏览器
from playwright.sync_api import sync_playwright
def launch_browser():
playwright = sync_playwright().start()
browser = playwright.chromium.launch(
headless=True, # Set False to see browser
args=['--remote-debugging-port=9222']
)
context = browser.new_context(
viewport={'width': 1920, 'height': 1080}
)
page = context.new_page()
return playwright, browser, context, page
2. 获取页面结构(无需截图)
def get_page_structure(page):
# Get accessibility tree
accessibility = page.accessibility.snapshot()
# Get all interactive elements
elements = page.query_selector_all('[role], button, a, input, select, [data-testid]')
structure = {
'url': page.url,
'title': page.title(),
'elements': []
}
for elem in elements:
if elem.is_visible():
structure['elements'].append({
'role': elem.get_attribute('role'),
'label': elem.get_attribute('aria-label') or elem.inner_text()[:100],
'type': elem.get_attribute('type'),
'testid': elem.get_attribute('data-testid'),
'enabled': elem.is_enabled(),
'selector': elem.evaluate('el => { const path = []; let current = el; while (current && current.tagName) { path.unshift(current.tagName.toLowerCase() + (current.id ? "#" + current.id : "") + (current.className ? "." + current.className.split(" ")[0] : "")); current = current.parentElement; } return path.join(" > "); }')
})
return structure
3. 自主导航
def navigate_and_verify(page, url, checkpoints):
print(f"🌐 Navigating to {url}")
page.goto(url, wait_until='networkidle')
page.wait_for_timeout(2000)
results = {
'url': page.url,
'title': page.title(),
'checkpoints': {},
'issues': []
}
for checkpoint_name, selector in checkpoints.items():
try:
elem = page.locator(selector)
visible = elem.is_visible()
results['checkpoints'][checkpoint_name] = {
'found': True,
'visible': visible,
'text': elem.inner_text()[:100] if visible else None
}
if not visible:
results['issues'].append(f"{checkpoint_name} not visible")
except:
results['checkpoints'][checkpoint_name] = {'found': False}
results['issues'].append(f"{checkpoint_name} not found")
return results
4. 元素交互
def interact_with_element(page, selector, action, value=None):
elem = page.locator(selector)
if action == 'click':
elem.click()
elif action == 'type':
elem.fill(value)
elif action == 'select':
elem.select_option(value)
elif action == 'hover':
elem.hover()
page.wait_for_timeout(500) # Wait for effects
5. 控制台和网络监控
def monitor_console_and_network(page):
errors = []
requests = []
page.on('console', lambda msg:
errors.append(msg.text) if msg.type == 'error' else None
)
page.on('request', lambda req:
requests.append({'url': req.url, 'method': req.method})
)
return errors, requests
预构建工作流
Lovable 预览验证
def verify_lovable_preview(project_id):
playwright, browser, context, page = launch_browser()
# Navigate to Lovable
url = f"https://lovable.dev/projects/{project_id}"
page.goto(url, wait_until='networkidle')
# Click Preview button
preview_btn = page.get_by_role("button", name="Preview")
if preview_btn.is_visible():
preview_btn.click()
page.wait_for_timeout(2000)
# Get preview page
pages = context.pages
preview_page = pages[-1] if len(pages) > 1 else page
# Verify checkpoints
checkpoints = {
'map_container': '[data-testid="map-container"], #map, .mapboxgl-map',
'header': 'header, [role="banner"], nav',
'markers': '[data-testid="marker"], .marker, .mapboxgl-marker',
'search': '[data-testid="search"], input[type="search"]'
}
results = navigate_and_verify(preview_page, preview_page.url, checkpoints)
# Test interactions
try:
map_elem = preview_page.locator('[data-testid="map-container"]')
if map_elem.is_visible():
# Zoom in
preview_page.keyboard.press('+')
page.wait_for_timeout(500)
# Zoom out
preview_page.keyboard.press('-')
page.wait_for_timeout(500)
results['interactions'] = {'zoom': 'SUCCESS'}
except Exception as e:
results['interactions'] = {'zoom': f'FAILED: {str(e)}'}
browser.close()
playwright.stop()
return results
BECA 抓取器 DOM 检查
def inspect_beca_login_form():
playwright, browser, context, page = launch_browser()
page.goto('https://beca.v3.target-url.com', wait_until='networkidle')
page.wait_for_timeout(3000)
# Get all form elements
forms = page.query_selector_all('form')
inputs = page.query_selector_all('input')
buttons = page.query_selector_all('button, input[type="submit"]')
results = {
'url': page.url,
'forms': [],
'inputs': [],
'buttons': []
}
for form in forms:
results['forms'].append({
'id': form.get_attribute('id'),
'class': form.get_attribute('class'),
'action': form.get_attribute('action'),
'method': form.get_attribute('method')
})
for inp in inputs:
if inp.is_visible():
results['inputs'].append({
'name': inp.get_attribute('name'),
'id': inp.get_attribute('id'),
'type': inp.get_attribute('type'),
'placeholder': inp.get_attribute('placeholder'),
'required': inp.get_attribute('required'),
'selector': f"input[name='{inp.get_attribute('name')}']" if inp.get_attribute('name') else f"input[id='{inp.get_attribute('id')}']"
})
for btn in buttons:
if btn.is_visible():
results['buttons'].append({
'text': btn.inner_text(),
'type': btn.get_attribute('type'),
'id': btn.get_attribute('id'),
'class': btn.get_attribute('class'),
'selector': f"button:has-text('{btn.inner_text()}')" if btn.tag_name == 'button' else f"input[type='{btn.get_attribute('type')}']"
})
browser.close()
playwright.stop()
return results
部署
安装依赖项
pip install playwright --break-system-packages
playwright install chromium
GitHub Actions 工作流
创建 .github/workflows/screen_control_operator.yml:
name: Screen Control Operator
on:
workflow_dispatch:
inputs:
task:
description: 'Task to execute'
required: true
type: choice
options:
- verify_lovable
- inspect_beca
- test_scrapers
target_url:
description: 'Target URL (optional)'
required: false
jobs:
execute:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Playwright
run: |
pip install playwright
playwright install chromium
- name: Execute Screen Control Task
run: |
python scripts/screen_control_operator.py --task ${{ github.event.inputs.task }} --url "${{ github.event.inputs.target_url }}"
- name: Upload Results
uses: actions/upload-artifact@v4
with:
name: screen-control-results
path: results.json
使用示例
在 Claude Chat 中使用
"Use screen-control-operator to verify Lovable preview"
"Inspect BECA login form with screen-control-operator"
"Test brevard-bidder-landing.pages.dev autonomously"
在命令行中使用
# Verify Lovable
python scripts/screen_control_operator.py verify-lovable fe59383e-3396-49f3-9cb9-5fea97dce977
# Inspect BECA
python scripts/screen_control_operator.py inspect-beca
# Test any URL
python scripts/screen_control_operator.py test-url https://brevard-bidder-landing.pages.dev
以编程方式使用
from scripts.screen_control_operator import verify_lovable_preview, inspect_beca_login_form
# Verify Lovable
results = verify_lovable_preview('fe59383e-3396-49f3-9cb9-5fea97dce977')
print(json.dumps(results, indent=2))
# Inspect BECA
beca_dom = inspect_beca_login_form()
print(f"Found {len(beca_dom['inputs'])} inputs, {len(beca_dom['buttons'])} buttons")
主要优势
- 无需截图——速度快 10 倍,可在无头 CI/CD 中运行
- 100% 可靠——语义查询不会因元素位置而失败
- 完整 DOM 访问——控制台日志、网络请求、元素状态
- 自主运行——无需人工介入,就像 GPT Operator 一样
- 支持 GitHub Actions——部署到云端,按计划运行
参考资料
有关实现细节:
scripts/screen_control_operator.py- 自主控制主脚本scripts/verify_lovable.py- Lovable 预览验证scripts/inspect_beca.py- BECA DOM 检查references/playwright_api.md- Playwright API 快速参考
评论
支持 Markdown