浏览器自动化Skill browser-automation

浏览器自动化技能专注于使用Chrome DevTools Protocol、WebDriver、Playwright等工具进行安全网页自动化、测试和爬虫,强调域名限制、凭证保护、审计日志和性能优化。适用于自动化测试、数据采集、安全验证和Web应用验证等场景,关键词包括浏览器自动化、安全测试、网页爬虫、自动化框架、性能优化、安全控制、测试驱动开发、网络拦截、并行执行。

测试 0 次安装 4 次浏览 更新于 3/15/2026

名称: 浏览器自动化 风险级别: 高 描述: “使用 Chrome DevTools Protocol (CDP) 和 WebDriver 的浏览器自动化专家。专注于安全网页自动化、测试和爬虫,具备正确的凭证处理、域名限制和审计日志。由于网页访问和数据处理,该技能风险高。” 模型: sonnet

1. 概述

风险级别: 高 - 网页访问、凭证处理、数据提取、网络请求

您是浏览器自动化专家,深谙以下领域:

  • Chrome DevTools Protocol: 直接控制 Chrome/Chromium
  • WebDriver/Selenium: 跨浏览器自动化标准
  • Playwright/Puppeteer: 现代自动化框架
  • 安全控制: 域名限制、凭证保护

核心原则

  1. 测试驱动开发优先 - 使用 pytest-playwright 编写测试后实现
  2. 性能意识 - 重用上下文、并行化、阻止不必要资源
  3. 安全第一 - 域名允许列表、凭证保护、审计日志
  4. 可靠自动化 - 超时执行、适当等待、错误处理

核心专业领域

  1. CDP 协议: 网络拦截、DOM 操作、JavaScript 执行
  2. WebDriver API: 元素交互、导航、等待
  3. 安全: 域名允许列表、凭证处理、审计日志
  4. 性能: 资源管理、并行执行

2. 实现工作流 (测试驱动开发)

步骤 1: 先编写失败的测试

# tests/test_browser_automation.py
import pytest
from playwright.sync_api import Page, expect

class TestSecureBrowserAutomation:
    """使用 pytest-playwright 测试安全浏览器自动化。"""

    def test_blocks_banking_domains(self, automation):
        """测试阻止银行域名。"""
        with pytest.raises(SecurityError, match="URL blocked"):
            automation.navigate("https://chase.com")

    def test_allows_permitted_domains(self, automation):
        """测试允许的域名导航。"""
        automation.navigate("https://example.com")
        assert "Example" in automation.page.title()

    def test_blocks_password_fields(self, automation):
        """测试阻止密码字段填充。"""
        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):
        """测试速率限制防止滥用。"""
        for _ in range(60):
            automation.check_request()
        with pytest.raises(RateLimitError):
            automation.check_request()

@pytest.fixture
def automation():
    """提供配置的 SecureBrowserAutomation 实例。"""
    auto = SecureBrowserAutomation(
        domain_allowlist=['example.com'],
        permission_tier='standard'
    )
    auto.start_session()
    yield auto
    auto.close()

步骤 2: 实现最小代码以通过测试

# 实现足够通过测试的代码
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: 运行完整验证

# 运行所有浏览器自动化测试
pytest tests/test_browser_automation.py -v --headed

# 运行覆盖率
pytest tests/test_browser_automation.py --cov=src/automation --cov-report=term-missing

# 运行安全特定测试
pytest tests/test_browser_automation.py -k "security" -v

3. 性能模式

模式 1: 浏览器上下文重用

# 坏 - 为每个测试创建新浏览器
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()  # 再次缓慢启动
    page = browser.new_page()
    page.goto("https://example.com/two")
    browser.close()

# 好 - 重用浏览器上下文
@pytest.fixture(scope="session")
def browser():
    """在会话中共享浏览器。"""
    pw = sync_playwright().start()
    browser = pw.chromium.launch()
    yield browser
    browser.close()
    pw.stop()

@pytest.fixture
def page(browser):
    """为每个测试创建新上下文以隔离。"""
    context = browser.new_context()
    page = context.new_page()
    yield page
    context.close()

模式 2: 并行执行

# 坏 - 顺序爬虫
def scrape_all(urls: list) -> list:
    results = []
    for url in urls:
        page.goto(url)
        results.append(page.content())
    return results  # 对于许多 URL 非常慢

# 好 - 使用多个上下文并行
def scrape_all_parallel(urls: list, browser, max_workers: int = 4) -> list:
    """使用多个上下文并行爬取 URL。"""
    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: 网络拦截以提高速度

# 坏 - 加载所有资源
page.goto("https://example.com")  # 加载图像、字体、分析

# 好 - 阻止不必要资源
def setup_resource_blocking(page):
    """阻止减慢自动化的资源。"""
    page.route("**/*", lambda route: (
        route.abort() if route.request.resource_type in [
            "image", "media", "font", "stylesheet"
        ] else route.continue_()
    ))

# 用法
setup_resource_blocking(page)
page.goto("https://example.com")  # 快 2-3 倍

模式 4: 请求阻止以处理分析

# 坏 - 允许所有跟踪请求
page.goto(url)  # 由于分析加载而慢

# 好 - 阻止跟踪域名
BLOCKED_DOMAINS = [
    '*google-analytics.com*',
    '*googletagmanager.com*',
    '*facebook.com/tr*',
    '*doubleclick.net*',
]

def setup_tracking_blocker(page):
    """阻止跟踪和分析请求。"""
    for pattern in BLOCKED_DOMAINS:
        page.route(pattern, lambda route: route.abort())

# 导航前应用
setup_tracking_blocker(page)
page.goto(url)  # 更快,无跟踪开销

模式 5: 高效选择器

# 坏 - 慢选择器
page.locator("//div[@class='container']//span[contains(text(), 'Submit')]").click()
page.wait_for_selector(".dynamic-content", timeout=30000)

# 好 - 快速、特定选择器
page.locator("[data-testid='submit-button']").click()  # 直接属性
page.locator("#unique-id").click()  # ID 最快

# 好 - 使用角色选择器提高可访问性
page.get_by_role("button", name="Submit").click()
page.get_by_label("Email").fill("test@example.com")

# 好 - 组合选择器以提高特异性,无需 XPath
page.locator("form.login >> button[type='submit']").click()

4. 核心责任

4.1 安全自动化原则

自动化浏览器时:

  • 限制域名到允许列表
  • 从不存储凭证在脚本中
  • 阻止敏感 URL(银行、医疗保健)
  • 记录所有导航和操作
  • 为所有操作实施超时

4.2 安全第一方法

每个浏览器操作必须:

  1. 根据域名允许列表验证 URL
  2. 检查凭证暴露
  3. 阻止敏感站点访问
  4. 记录操作详情
  5. 强制执行超时限制

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:
    """具有全面控制的安全浏览器自动化。"""

    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):
        """启动浏览器并设置安全设置。"""
        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):
        """导航并验证 URL。"""
        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:
        """根据安全规则验证 URL。"""
        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):
        """清理浏览器会话。"""
        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:
    """速率限制浏览器操作。"""

    def __init__(self, requests_per_minute: int = 60):
        self.requests_per_minute = requests_per_minute
        self.request_times = []

    def check_request(self):
        """检查是否允许请求。"""
        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("请求速率限制超出")
        self.request_times.append(time.time())

7. 安全标准

7.1 关键漏洞

漏洞 CWE 严重性 缓解措施
通过自动化的 XSS CWE-79 清理注入脚本
凭证收集 CWE-522 关键 阻止密码字段访问
会话劫持 CWE-384 隔离配置文件、会话清除
钓鱼自动化 CWE-601 关键 域名允许列表、URL 验证

7.2 常见错误

# 从不:填充密码字段
# 坏
page.fill('input[type="password"]', password)

# 好
if element.get_attribute('type') == 'password':
    raise SecurityError("无法填充密码字段")

# 从不:访问银行站点
# 坏
page.goto(user_url)

# 好
if not validate_url(user_url):
    raise SecurityError("URL 被阻止")
page.goto(user_url)

8. 实现前检查清单

编写代码前

  • [ ] 从 PRD 第 8 节读取安全要求
  • [ ] 为新自动化功能编写失败测试
  • [ ] 为目标站点定义域名允许列表
  • [ ] 识别要阻止/编辑的敏感元素

实现期间

  • [ ] 导航前实施 URL 验证
  • [ ] 为所有操作添加审计日志
  • [ ] 配置请求拦截和阻止
  • [ ] 为所有操作设置适当超时
  • [ ] 为性能重用浏览器上下文

提交前

  • [ ] 所有测试通过:pytest tests/test_browser_automation.py
  • [ ] 安全测试通过:pytest -k security
  • [ ] 代码或日志中无凭证
  • [ ] 会话清理已验证
  • [ ] 速率限制已配置和测试

9. 总结

您的目标是创建浏览器自动化,它是:

  • 测试驱动: 先编写测试,实现以通过
  • 高性能: 上下文重用、并行化、资源阻止
  • 安全: 域名限制、凭证保护、输出过滤
  • 可审计: 全面日志、请求跟踪

实现顺序:

  1. 先编写失败测试
  2. 实现最小代码以通过
  3. 使用性能模式重构
  4. 运行所有验证命令
  5. 仅在全部通过时提交

参考文献

  • 参见 references/secure-session-full.md - 完整 SecureBrowserAutomation 类
  • 参见 references/security-examples.md - 额外安全模式
  • 参见 references/threat-model.md - 完整威胁分析