← 返回 Skills 市场
sky-lv

Skylv Web Automation Bot

作者 SKY-lv · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
42
总下载
0
收藏
0
当前安装
1
版本数
在 OpenClaw 中安装
/install skylv-web-automation-bot
功能描述
AI-driven browser automation for web scraping, form filling, and UI interactions using Playwright or Puppeteer libraries.
使用说明 (SKILL.md)

Browser Automation Agent

功能说明

AI驱动的浏览器自动化,执行复杂网页任务。

技术选型

特点 适用场景
Playwright 跨浏览器、等待稳定 通用自动化
Puppeteer Chrome专用、Node原生 Chrome深度控制
Selenium 多语言、老牌稳定 多浏览器兼容
DrissionPage Python、轻量 中国网站适配

Playwright 完整实现

1. 基础框架

from playwright.sync_api import sync_playwright, Page, Browser, BrowserContext
from dataclasses import dataclass
from typing import Optional
import json

@dataclass
class TaskResult:
    success: bool
    data: Optional[dict] = None
    error: Optional[str] = None
    screenshot: Optional[str] = None

class BrowserAgent:
    def __init__(self, headless: bool = True, slow_mo: int = 100):
        self.playwright = sync_playwright().start()
        self.browser: Browser = self.playwright.chromium.launch(
            headless=headless,
            slow_mo=slow_mo
        )
        self.context: BrowserContext = self.browser.new_context(
            viewport={"width": 1920, "height": 1080},
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        )
    
    def new_page(self) -> Page:
        return self.context.new_page()
    
    def execute(self, task: str) -> TaskResult:
        """执行AI指令"""
        page = self.new_page()
        try:
            # AI解析任务
            steps = self.plan_steps(task)
            
            for step in steps:
                self.execute_step(page, step)
            
            return TaskResult(success=True, data={"steps_completed": len(steps)})
        except Exception as e:
            return TaskResult(success=False, error=str(e))
        finally:
            page.close()
    
    def plan_steps(self, task: str) -> list[dict]:
        """AI规划步骤"""
        # 这里集成LLM进行任务规划
        # ...
        pass
    
    def execute_step(self, page: Page, step: dict):
        action = step["action"]
        
        if action == "goto":
            page.goto(step["url"], wait_until="domcontentloaded")
        elif action == "click":
            page.click(step["selector"])
        elif action == "type":
            page.fill(step["selector"], step["text"])
        elif action == "wait":
            page.wait_for_timeout(step["ms"])
        elif action == "screenshot":
            page.screenshot(path=step["path"])
        elif action == "extract":
            return page.query_selector(step["selector"]).inner_text()
    
    def close(self):
        self.browser.close()
        self.playwright.stop()

2. 智能元素定位

class SmartLocator:
    """AI智能定位器"""
    
    LOCATOR_STRATEGIES = [
        "get_by_role",      # 无障碍角色(最可靠)
        "get_by_label",     # 表单标签
        "get_by_placeholder",  # 占位符
        "get_by_text",      # 文本内容
        "locator",          # CSS选择器
        "xpath",             # XPath(最后备选)
    ]
    
    def find(self, page: Page, description: str) -> Locator:
        """根据描述智能查找元素"""
        strategies = [
            # 按钮查找
            lambda: page.get_by_role("button", name=description),
            lambda: page.get_by_role("link", name=description),
            
            # 输入框查找
            lambda: page.get_by_label(description),
            lambda: page.get_by_placeholder(description),
            
            # 文本查找
            lambda: page.get_by_text(description, exact=True),
            lambda: page.get_by_text(description),
            
            # 通配符(放在最后)
            lambda: page.locator(f"text={description}").first,
        ]
        
        for strategy in strategies:
            try:
                locator = strategy()
                if locator.count() > 0:
                    return locator.first
            except:
                continue
        
        raise ElementNotFound(f"找不到元素: {description}")
    
    def find_many(self, page: Page, description: str) -> list:
        """批量查找元素"""
        # 尝试多种策略
        # ...
        pass

3. 表单自动填写

class FormFiller:
    """智能表单填写"""
    
    def fill_form(self, page: Page, form_data: dict):
        """根据字段描述自动填写"""
        for field_name, value in form_data.items():
            try:
                # 尝试找对应label的输入框
                locator = page.get_by_label(field_name, exact=False)
                
                # 获取输入类型
                if locator.count() == 0:
                    # 尝试placeholder
                    locator = page.get_by_placeholder(field_name)
                
                if locator.count() == 0:
                    # 尝试名称属性
                    locator = page.locator(f'[name="{field_name}"]')
                
                if locator.count() > 0:
                    el = locator.first
                    tag = el.evaluate("el => el.tagName")
                    
                    if tag == "SELECT":
                        el.select_option(value)
                    elif tag == "INPUT":
                        input_type = el.get_attribute("type")
                        if input_type in ["checkbox", "radio"]:
                            if value:
                                el.check()
                        else:
                            el.fill(str(value))
                    else:
                        el.fill(str(value))
                        
            except Exception as e:
                print(f"填写字段 {field_name} 失败: {e}")
    
    def extract_form(self, page: Page, form_selector: str = "form") -> dict:
        """提取表单数据"""
        form = page.locator(form_selector).first
        data = {}
        
        inputs = form.locator("input, select, textarea")
        for inp in inputs.all():
            name = inp.get_attribute("name") or inp.get_attribute("id")
            if not name: continue
            
            input_type = inp.get_attribute("type") or "text"
            if input_type in ["submit", "button", "reset", "image"]: continue
            
            if input_type == "checkbox":
                data[name] = inp.is_checked()
            elif input_type == "radio":
                checked = form.locator(f'input[name="{name}"]:checked')
                data[name] = checked.get_attribute("value") if checked.count() > 0 else None
            else:
                data[name] = inp.input_value()
        
        return data

4. 数据采集

class WebScraper:
    """网页数据采集"""
    
    def scrape_table(self, page: Page, table_selector: str) -> list[dict]:
        """采集表格数据"""
        table = page.locator(table_selector).first
        
        # 获取表头
        headers = table.locator("thead th, th").all_text_contents()
        
        # 采集每行
        rows = []
        for row in table.locator("tbody tr, tr").all():
            cells = row.locator("td, th").all_text_contents()
            if len(cells) == len(headers):
                rows.append(dict(zip(headers, cells)))
        
        return rows
    
    def scrape_cards(self, page: Page, card_selector: str, fields: dict) -> list[dict]:
        """采集卡片式列表"""
        cards = page.locator(card_selector).all()
        results = []
        
        for card in cards:
            item = {}
            for field_name, selector in fields.items():
                try:
                    el = card.locator(selector).first
                    item[field_name] = el.inner_text().strip()
                except:
                    item[field_name] = None
            results.append(item)
        
        return results
    
    def scroll_scrape(self, page: Page, item_selector: str, max_items: int = 100) -> list:
        """滚动加载采集"""
        items = []
        last_count = 0
        
        while len(items) \x3C max_items:
            # 滚动
            page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
            page.wait_for_timeout(1000)
            
            # 采集新数据
            new_items = page.locator(item_selector).all_text_contents()
            items.extend(new_items[last_count:])
            last_count = len(items)
            
            # 检查是否到底
            if len(items) == last_count:
                break
        
        return items[:max_items]

5. 反爬对抗

class AntiDetection:
    """反检测"""
    
    @staticmethod
    def stealth(context: BrowserContext):
        """Stealth模式"""
        # 随机User-Agent
        ua_list = [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/17.2",
        ]
        context.set_extra_http_headers({"User-Agent": random.choice(ua_list)})
        
        # 注入反检测脚本
        context.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
            window.chrome = { runtime: {} };
        """)
    
    @staticmethod
    def human_delay(page: Page, min_ms=50, max_ms=200):
        """模拟人类延迟"""
        import random
        import time
        time.sleep(random.uniform(min_ms, max_ms) / 1000)

Puppeteer 实现

const { chromium } = require('puppeteer');

class BrowserAutomation {
  async init() {
    this.browser = await chromium.launch({ 
      headless: true,
      args: ['--disable-blink-features=AutomationControlled']
    });
    
    // Stealth
    const context = await this.browser.newContext({
      viewport: { width: 1920, height: 1080 },
      userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    });
    
    // Remove webdriver flag
    await context.addInitScript(() => {
      Object.defineProperty(navigator, 'webdriver', { get: () => false });
    });
    
    this.page = await context.newPage();
  }
  
  async goto(url) {
    await this.page.goto(url, { waitUntil: 'networkidle2' });
    await this.page.waitForTimeout(1000);
  }
  
  async click(selector) {
    await this.page.locator(selector).first().click();
  }
  
  async type(selector, text) {
    await this.page.locator(selector).fill(text);
  }
  
  async extract(selector) {
    return await this.page.locator(selector).allTextContents();
  }
  
  async screenshot(path) {
    await this.page.screenshot({ path, fullPage: true });
  }
  
  async close() {
    await this.browser.close();
  }
}

常见任务模板

登录 + 数据采集

with BrowserAgent() as agent:
    page = agent.new_page()
    
    # 登录
    page.goto("https://example.com/login")
    page.fill("#username", "[email protected]")
    page.fill("#password", "password123")
    page.click("button[type='submit']")
    page.wait_for_url("**/dashboard")
    
    # 采集数据
    page.goto("https://example.com/data")
    data = WebScraper().scrape_table(page, "table.data")
    
    print(data)

批量截图

urls = ["https://site1.com", "https://site2.com", "https://site3.com"]
with BrowserAgent() as agent:
    for i, url in enumerate(urls):
        page = agent.new_page()
        page.goto(url, wait_until="networkidle")
        page.screenshot(path=f"screenshot_{i}.png")
        page.close()

最佳实践

  1. 等待策略:用 wait_for_selector 而不是固定sleep
  2. 重试机制:网络不稳定时自动重试
  3. 异常处理:每个操作都要try-catch
  4. 资源清理:总是关闭page和context
  5. 隐身模式:每个任务用独立的context避免cookies污染

Usage

  1. Install the skill
  2. Configure as needed
  3. Run with OpenClaw
安全使用建议
Install only if you want an agent that can automate websites. Run it in a fresh or isolated browser context when possible, limit it to trusted domains, avoid using it on logged-in accounts unless necessary, and require explicit confirmation before any submission, purchase, account change, or other irreversible action.
功能分析
Type: OpenClaw Skill Name: skylv-web-automation-bot Version: 1.0.0 The skill bundle provides a legitimate and well-structured framework for browser automation using Playwright and Puppeteer, as described in SKILL.md and skill.json. It includes helper classes for intelligent element discovery, automated form filling, and web scraping, along with standard anti-detection techniques. No evidence of malicious intent, data exfiltration, or harmful prompt injection was found; the code is entirely consistent with its stated purpose of UI automation.
能力评估
Purpose & Capability
The stated purpose is coherent with the artifacts: browser automation, scraping, form filling, and UI automation using Playwright/Puppeteer. Users should still notice that this kind of skill can act on websites on their behalf.
Instruction Scope
The documented implementation plans steps from a task and directly executes navigation, clicking, typing, screenshots, and extraction with no shown confirmation gates, URL allowlists, or sensitive-action limits.
Install Mechanism
The registry describes an instruction-only skill with no install spec or code files, while the documentation references Playwright/Puppeteer-style runtime code. This is not itself malicious, but the actual runtime dependencies and implementation are outside the scan.
Credentials
Browser network access, DOM extraction, form filling, and screenshot file writes are proportional to the stated purpose, but should be scoped to intended sites and safe output paths.
Persistence & Privilege
No artifact evidence shows background persistence, credential storage, local browser profile reuse, or elevated privileges; the shown sample creates a browser context and includes close logic.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install skylv-web-automation-bot
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /skylv-web-automation-bot 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.0
Initial release of the browser automation agent. - Supports AI-driven web automation using Playwright or Puppeteer for scraping, form filling, and UI interaction. - Implements a base framework for automated task execution and step planning. - Features intelligent element location, smart form filling/extraction, and data scraping tools for tables and cards. - Designed for compatibility with multiple web automation libraries and scenarios. - Includes sample code and technical documentation.
元数据
Slug skylv-web-automation-bot
版本 1.0.0
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 1
常见问题

Skylv Web Automation Bot 是什么?

AI-driven browser automation for web scraping, form filling, and UI interactions using Playwright or Puppeteer libraries. 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 42 次。

如何安装 Skylv Web Automation Bot?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install skylv-web-automation-bot」即可一键安装,无需额外配置。

Skylv Web Automation Bot 是免费的吗?

是的,Skylv Web Automation Bot 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Skylv Web Automation Bot 支持哪些平台?

Skylv Web Automation Bot 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Skylv Web Automation Bot?

由 SKY-lv(@sky-lv)开发并维护,当前版本 v1.0.0。

💬 留言讨论