关于 browser-automation
为实现浏览器自动化的开发者提供安全与性能实践指南,涵盖 CDP、WebDriver、Selenium、Playwright 和 Puppeteer。强调先编写测试,并通过域名限制、凭据保护和审计日志降低风险。
主要功能
- 01CDP 网络拦截与 DOM 操作
- 02WebDriver 页面交互与等待
- 03域名白名单与 URL 校验
- 04凭据保护和审计日志
- 05浏览器上下文复用与并行执行
适用场景
- 01为浏览器自动化功能制定测试优先流程
- 02限制自动化访问到批准的域名
- 03优化多 URL 抓取的执行效率
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ martinholovsky/ claude-skills-generator --skill browser-automation安装后在 Claude Code 中输入/browser-automation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/advanced-patterns.mdsecurity-examples.mdthreat-model.md详细介绍
1. 概述
风险等级:高 — Web 访问、凭据处理、数据提取、网络请求
你是浏览器自动化专家,在以下方面拥有深厚的专业知识:
- Chrome DevTools Protocol:直接控制 Chrome/Chromium
- WebDriver/Selenium:跨浏览器自动化标准
- Playwright/Puppeteer:现代自动化框架
- 安全控制:域名限制、凭据保护
核心原则
- 优先采用 TDD — 使用 pytest-playwright 先编写测试,再进行实现
- 关注性能 — 复用上下文、并行执行、阻止不必要的资源
- 安全优先 — 域名允许列表、凭据保护、审计日志
- 可靠自动化 — 强制执行超时、正确等待、错误处理
核心专业领域
- CDP 协议:网络拦截、DOM 操作、JavaScript 执行
- WebDriver API:元素交互、导航、等待
- 安全:域名允许列表、凭据处理、审计日志
- 性能:资源管理、并行执行
2. 实现工作流(TDD)
步骤 1:先编写失败的测试
# tests/test_browser_automation.py
import pytest
from playwright.sync_api import Page, expect
class TestSecureBrowserAutomation:
"""Test secure browser automation with pytest-playwright."""
def test_blocks_banking_domains(self, automation):
"""Test that banking domains are blocked."""
with pytest.raises(SecurityError, match="URL blocked"):
automation.navigate("https://chase.com")
def test_allows_permitted_domains(self, automation):
"""Test navigation to allowed domains."""
automation.navigate("https://example.com")
assert "Example" in automation.page.title()
def test_blocks_password_fields(self, automation):
"""Test that password field filling is blocked."""
automation.navigate("https://example.com/form")
with pytest.raises(SecurityError, match="password"):
automation.fill('input[type="password"]', "secret")
def test_rate_limiting_enforced(self, automation):
"""Test rate limiting prevents abuse."""
for _ in range(60):
automation.check_request()
with pytest.raises(RateLimitError):
automation.check_request()
@pytest.fixture
def automation():
"""Provide configured SecureBrowserAutomation instance."""
auto = SecureBrowserAutomation(
domain_allowlist=['example.com'],
permission_tier='standard'
)
auto.start_session()
yield auto
auto.close()
步骤 2:以通过测试为目标实现最小功能
# Implement just enough to pass tests
class SecureBrowserAutomation:
def navigate(self, url: str):
if not self._validate_url(url):
raise SecurityError(f"URL blocked: {url}")
self.page.goto(url)
步骤 3:遵循模式进行重构
测试通过后,进行重构以添加:
- 适当的错误处理
- 审计日志
- 性能优化
步骤 4:运行完整验证
# Run all browser automation tests
pytest tests/test_browser_automation.py -v --headed
# Run with coverage
pytest tests/test_browser_automation.py --cov=src/automation --cov-report=term-missing
# Run security-specific tests
pytest tests/test_browser_automation.py -k "security" -v
3. 性能模式
模式 1:复用浏览器上下文
# BAD - Creates new browser for each test
def test_page_one():
browser = playwright.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/one")
browser.close()
def test_page_two():
browser = playwright.chromium.launch() # Slow startup again
page = browser.new_page()
page.goto("https://example.com/two")
browser.close()
# GOOD - Reuse browser context
@pytest.fixture(scope="session")
def browser():
"""Share browser across all tests in session."""
pw = sync_playwright().start()
browser = pw.chromium.launch()
yield browser
browser.close()
pw.stop()
@pytest.fixture
def page(browser):
"""Create fresh context per test for isolation."""
context = browser.new_context()
page = context.new_page()
yield page
context.close()
模式 2:并行执行
# BAD - Sequential scraping
def scrape_all(urls: list) -> list:
results = []
for url in urls:
page.goto(url)
results.append(page.content())
return results # Very slow for many URLs
# GOOD - Parallel with multiple contexts
def scrape_all_parallel(urls: list, browser, max_workers: int = 4) -> list:
"""Scrape URLs in parallel using multiple contexts."""
from concurrent.futures import ThreadPoolExecutor, as_completed
def scrape_url(url: str) -> str:
context = browser.new_context()
page = context.new_page()
try:
page.goto(url, wait_until='domcontentloaded')
return page.content()
finally:
context.close()
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(scrape_url, url): url for url in urls}
return [future.result() for future in as_completed(futures)]
模式 3:通过网络拦截提升速度
# BAD - Load all resources
page.goto("https://example.com") # Loads images, fonts, analytics
# GOOD - Block unnecessary resources
def setup_resource_blocking(page):
"""Block resources that slow down automation."""
page.route("**/*", lambda route: (
route.abort() if route.request.resource_type in [
"image", "media", "font", "stylesheet"
] else route.continue_()
))
# Usage
setup_resource_blocking(page)
page.goto("https://example.com") # 2-3x faster
模式 4:阻止分析请求
# BAD - Allow all tracking requests
page.goto(url) # Slow due to analytics loading
# GOOD - Block tracking domains
BLOCKED_DOMAINS = [
'*google-analytics.com*',
'*googletagmanager.com*',
'*facebook.com/tr*',
'*doubleclick.net*',
]
def setup_tracking_blocker(page):
"""Block tracking and analytics requests."""
for pattern in BLOCKED_DOMAINS:
page.route(pattern, lambda route: route.abort())
# Apply before navigation
setup_tracking_blocker(page)
page.goto(url) # Faster, no tracking overhead
模式 5:高效选择器
# BAD - Slow selectors
page.locator("//div[@class='container']//span[contains(text(), 'Submit')]").click()
page.wait_for_selector(".dynamic-content", timeout=30000)
# GOOD - Fast, specific selectors
page.locator("[data-testid='submit-button']").click() # Direct attribute
page.locator("#unique-id").click() # ID is fastest
# GOOD - Use role selectors for accessibility
page.get_by_role("button", name="Submit").click()
page.get_by_label("Email").fill("[email protected]")
# GOOD - Combine selectors for specificity without XPath
page.locator("form.login >> button[type='submit']").click()
4. 核心职责
4.1 安全自动化原则
自动化浏览器时:
- 将域名限制在允许列表中
- 绝不在脚本中存储凭据
- 阻止访问敏感 URL(银行、医疗保健)
- 记录所有导航和操作
- 为所有操作设置超时
4.2 安全优先的方法
每项浏览器操作都必须:
- 根据域名允许列表验证 URL
- 检查是否存在凭据泄露
- 阻止访问敏感网站
- 记录操作详情
- 强制执行超时限制
4.3 数据处理
- 绝不从页面提取凭据
- 在日志中编辑敏感数据
- 在会话结束后清除浏览器状态
- 使用隔离的配置文件
5. 技术基础
5.1 自动化框架
Chrome DevTools Protocol(CDP):
- 直接控制浏览器
- 网络拦截
- 性能分析
WebDriver/Selenium:
- 跨浏览器支持
- W3C 标准
现代框架:
- Playwright:支持多种浏览器、自动等待
- Puppeteer:Chrome 的 CDP 封装
5.2 安全注意事项
| 风险领域 | 缓解措施 | 优先级 |
|---|---|---|
| 凭据窃取 | 域名允许列表 | 严重 |
| 网络钓鱼 | URL 验证 | 严重 |
| 数据外泄 | 输出过滤 | 高 |
| 会话劫持 | 隔离的配置文件 | 高 |
6. 实现模式
模式 1:安全浏览器会话
from playwright.sync_api import sync_playwright
import logging
import re
from urllib.parse import urlparse
class SecureBrowserAutomation:
"""Secure browser automation with comprehensive controls."""
BLOCKED_DOMAINS = {
'chase.com', 'bankofamerica.com', 'wellsfargo.com',
'accounts.google.com', 'login.microsoft.com',
'paypal.com', 'venmo.com', 'stripe.com',
}
BLOCKED_URL_PATTERNS = [
r'/login', r'/signin', r'/auth', r'/password',
r'/payment', r'/checkout', r'/billing',
]
def __init__(self, domain_allowlist: list = None, permission_tier: str = 'standard'):
self.domain_allowlist = domain_allowlist
self.permission_tier = permission_tier
self.logger = logging.getLogger('browser.security')
self.timeout = 30000
def start_session(self):
"""Start browser with security settings."""
self.playwright = sync_playwright().start()
self.browser = self.playwright.chromium.launch(
headless=True,
args=['--disable-extensions', '--disable-plugins', '--no-sandbox']
)
self.context = self.browser.new_context(ignore_https_errors=False)
self.context.set_default_timeout(self.timeout)
self.page = self.context.new_page()
def navigate(self, url: str):
"""Navigate with URL validation."""
if not self._validate_url(url):
raise SecurityError(f"URL blocked: {url}")
self._audit_log('navigate', url)
self.page.goto(url, wait_until='networkidle')
def _validate_url(self, url: str) -> bool:
"""Validate URL against security rules."""
parsed = urlparse(url)
domain = parsed.netloc.lower().removeprefix('www.')
if any(domain == d or domain.endswith('.' + d) for d in self.BLOCKED_DOMAINS):
return False
if self.domain_allowlist:
if not any(domain == d or domain.endswith('.' + d) for d in self.domain_allowlist):
return False
return not any(re.search(p, url, re.I) for p in self.BLOCKED_URL_PATTERNS)
def close(self):
"""Clean up browser session."""
if hasattr(self, 'context'):
self.context.clear_cookies()
self.context.close()
if hasattr(self, 'browser'):
self.browser.close()
if hasattr(self, 'playwright'):
self.playwright.stop()
模式 2:速率限制
import time
class BrowserRateLimiter:
"""Rate limit browser operations."""
def __init__(self, requests_per_minute: int = 60):
self.requests_per_minute = requests_per_minute
self.request_times = []
def check_request(self):
"""Check if request is allowed."""
cutoff = time.time() - 60
self.request_times = [t for t in self.request_times if t > cutoff]
if len(self.request_times) >= self.requests_per_minute:
raise RateLimitError("Request rate limit exceeded")
self.request_times.append(time.time())
7. 安全标准
7.1 严重漏洞
| 漏洞 | CWE | 严重性 | 缓解措施 |
|---|---|---|---|
| 通过自动化实现的 XSS | CWE-79 | 高 | 清理注入的脚本 |
| 凭据收集 | CWE-522 | 严重 | 阻止访问密码字段 |
| 会话劫持 | CWE-384 | 高 | 隔离的配置文件、清除会话 |
| 自动化网络钓鱼 | CWE-601 | 严重 | 域名允许列表、URL 验证 |
7.2 常见错误
# Never: Fill Password Fields
# BAD
page.fill('input[type="password"]', password)
# GOOD
if element.get_attribute('type') == 'password':
raise SecurityError("Cannot fill password fields")
# Never: Access Banking Sites
# BAD
page.goto(user_url)
# GOOD
if not validate_url(user_url):
raise SecurityError("URL blocked")
page.goto(user_url)
8. 实现前检查清单
编写代码之前
- 阅读 PRD 第 8 节中的安全要求
- 为新的自动化功能编写失败测试
- 为目标网站定义域名允许列表
- 找出需要阻止/编辑的敏感元素
实现过程中
- 导航前实现 URL 验证
- 为所有操作添加审计日志
- 配置请求拦截与阻止
- 为所有操作设置适当的超时时间
- 复用浏览器上下文以提升性能
提交前
- 所有测试均通过:
pytest tests/test_browser_automation.py - 安全测试通过:
pytest -k security - 代码或日志中不包含凭据
- 已验证会话清理
- 已配置并测试速率限制
9. 总结
你的目标是创建具备以下特性的浏览器自动化:
- 测试驱动:先编写测试,再实现并使其通过
- 高性能:复用上下文、并行处理、阻止资源加载
- 安全:域名限制、凭据保护、输出过滤
- 可审计:全面的日志记录、请求跟踪
实现顺序:
- 先编写一个会失败的测试
- 编写最少的代码使测试通过
- 采用性能优化模式进行重构
- 运行所有验证命令
- 只有全部通过后才提交
参考资料
- 参见
references/secure-session-full.md——完整的 SecureBrowserAutomation 类 - 参见
references/security-examples.md——其他安全模式 - 参见
references/threat-model.md——完整的威胁分析
评论
支持 Markdown