Create SKILL.md for Playwright Go Automation
Added comprehensive guidelines for using Playwright Go for browser automation, including architecture, logging, error handling, and stealth techniques.
This commit is contained in:
161
skills/go-playwright/SKILL.md
Normal file
161
skills/go-playwright/SKILL.md
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
---
|
||||||
|
name: playwright-go-automation
|
||||||
|
description: Expert capability for robust, stealthy, and efficient browser automation using Playwright Go.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Playwright Go Automation Expert
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This skill provides a comprehensive framework for writing high-performance, production-grade browser automation scripts using `github.com/playwright-community/playwright-go`. It enforces architectural best practices (contexts over instances), robust error handling, structured logging (Zap), and advanced human-emulation techniques to bypass anti-bot systems.
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
- Use when the user asks to "scrape," "automate," or "test" a website using Go.
|
||||||
|
- Use when the target site has complex dynamic content (SPA, React, Vue) requiring a real browser.
|
||||||
|
- Use when the user mentions "stealth," "avoiding detection," "cloudflare," or "human-like" behavior.
|
||||||
|
- Use when debugging existing Playwright scripts.
|
||||||
|
|
||||||
|
## Strategic Implementation Guidelines
|
||||||
|
|
||||||
|
### 1. Architecture: Contexts vs. Browsers
|
||||||
|
**CRITICAL:** Never launch a new `Browser` instance for every task.
|
||||||
|
- **Pattern:** Launch the `Browser` *once* (singleton). Create a new `BrowserContext` for each distinct session or task.
|
||||||
|
- **Why:** Contexts are lightweight and created in milliseconds. Browsers take seconds to launch.
|
||||||
|
- **Isolation:** Contexts provide complete isolation (cookies, cache, storage) without the overhead of a new process.
|
||||||
|
|
||||||
|
### 2. Logging & Observability
|
||||||
|
- **Library:** Use `go.uber.org/zap` exclusively.
|
||||||
|
- **Rule:** Do not use `fmt.Println`.
|
||||||
|
- **Modes:**
|
||||||
|
- **Dev:** `zap.NewDevelopment()` (Console friendly)
|
||||||
|
- **Prod:** `zap.NewProduction()` (JSON structured)
|
||||||
|
- **Traceability:** Log every navigation, click, and input with context fields (e.g., `logger.Info("clicking button", zap.String("selector", sel))`).
|
||||||
|
|
||||||
|
### 3. Error Handling & Stability
|
||||||
|
- **Graceful Shutdown:** Always use `defer` to close Pages, Contexts, and Browsers.
|
||||||
|
- **Panic Recovery:** Wrap critical automation routines in a safe runner that recovers panics and logs the stack trace.
|
||||||
|
- **Timeouts:** Never rely on default timeouts. Set explicit timeouts (e.g., `playwright.PageClickOptions{Timeout: playwright.Float(5000)}`).
|
||||||
|
|
||||||
|
### 4. Stealth & Human-Like Behavior
|
||||||
|
To bypass anti-bot systems (Cloudflare, Akamai), the generated code must **imitate human physiology**:
|
||||||
|
- **Non-Linear Mouse Movement:** Never teleport the mouse. Implement a helper that moves the mouse along a Bezier curve with random jitter.
|
||||||
|
- **Input Latency:** never use `Fill()`. Use `Type()` with random delays between keystrokes (50ms–200ms).
|
||||||
|
- **Viewport Randomization:** Randomize the viewport size slightly (e.g., 1920x1080 ± 15px) to avoid fingerprinting.
|
||||||
|
- **Behavioral Noise:** Randomly scroll, focus/unfocus the window, or hover over irrelevant elements ("idling") during long waits.
|
||||||
|
- **User-Agent:** Rotate User-Agents for every new Context.
|
||||||
|
|
||||||
|
### 5. Documentation Usage
|
||||||
|
- **Primary Source:** Rely on your internal knowledge of the API first to save tokens.
|
||||||
|
- **Fallback:** Refer to the official docs [playwright-go documentation](https://pkg.go.dev/github.com/playwright-community/playwright-go#section-documentation) ONLY if:
|
||||||
|
- You encounter an unknown error.
|
||||||
|
- You need to implement complex network interception or authentication flows.
|
||||||
|
- The API has changed significantly.
|
||||||
|
|
||||||
|
## Code Examples
|
||||||
|
|
||||||
|
### Standard Initialization (Headless + Zap)
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"[github.com/playwright-community/playwright-go](https://github.com/playwright-community/playwright-go)"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 1. Setup Logger
|
||||||
|
logger, _ := zap.NewDevelopment()
|
||||||
|
defer logger.Sync()
|
||||||
|
|
||||||
|
// 2. Start Playwright Driver
|
||||||
|
pw, err := playwright.Run()
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("could not start playwright", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Launch Browser (Singleton)
|
||||||
|
// Use Headless: false and SlowMo for Debugging
|
||||||
|
browser, err := pw.Chromium.Launch(playwright.BrowserTypeLaunchOptions{
|
||||||
|
Headless: playwright.Bool(false),
|
||||||
|
SlowMo: playwright.Float(100), // Slow actions by 100ms for visibility
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("could not launch browser", zap.Error(err))
|
||||||
|
}
|
||||||
|
defer browser.Close() // Graceful cleanup
|
||||||
|
|
||||||
|
// 4. Create Isolated Context (Session)
|
||||||
|
context, err := browser.NewContext(playwright.BrowserNewContextOptions{
|
||||||
|
UserAgent: playwright.String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)..."),
|
||||||
|
Viewport: &playwright.Size{Width: 1920, Height: 1080},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("could not create context", zap.Error(err))
|
||||||
|
}
|
||||||
|
defer context.Close()
|
||||||
|
|
||||||
|
// 5. Open Page
|
||||||
|
page, _ := context.NewPage()
|
||||||
|
|
||||||
|
// ... Implementation ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Human-Like Typing & Interaction
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HumanType simulates a user typing with variable speed
|
||||||
|
func HumanType(locator playwright.Locator, text string) {
|
||||||
|
// Focus the element first (like a human)
|
||||||
|
locator.Click()
|
||||||
|
|
||||||
|
for _, char := range text {
|
||||||
|
// Random delay: 50ms to 150ms
|
||||||
|
delay := time.Duration(rand.Intn(100) + 50) * time.Millisecond
|
||||||
|
time.Sleep(delay)
|
||||||
|
locator.Press(string(char))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HumanClick adds offset and hesitation
|
||||||
|
func HumanClick(page playwright.Page, selector string) {
|
||||||
|
box, _ := page.Locator(selector).BoundingBox()
|
||||||
|
if box == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate center with random offset (jitter)
|
||||||
|
x := box.X + box.Width/2 + (rand.Float64()*10 - 5)
|
||||||
|
y := box.Y + box.Height/2 + (rand.Float64()*10 - 5)
|
||||||
|
|
||||||
|
// Move mouse smoothly (requires custom Bezier implementation or steps)
|
||||||
|
page.Mouse().Move(x, y, playwright.MouseMoveOptions{Steps: playwright.Int(10)})
|
||||||
|
time.Sleep(100 * time.Millisecond) // Hesitate
|
||||||
|
page.Mouse().Click(x, y)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#Session Management (Save/Load Cookies)
|
||||||
|
|
||||||
|
```go
|
||||||
|
func SaveSession(context playwright.BrowserContext, filepath string) {
|
||||||
|
cookies, _ := context.Cookies()
|
||||||
|
// Serialize cookies to JSON and write to 'filepath'
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadSession(context playwright.BrowserContext, filepath string) {
|
||||||
|
// Read JSON from 'filepath' and deserialize
|
||||||
|
// var cookies []playwright.Cookie
|
||||||
|
context.AddCookies(cookies)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Summary Checklist for Agent
|
||||||
|
- Is Debug Mode on? -> Headless=false, SlowMo=100+.
|
||||||
|
- Is it a new user identity? -> Create NewContext, apply new Proxy, rotate User-Agent.
|
||||||
|
- Is the action critical? -> Wrap in SafeAction with zap logging.
|
||||||
|
- Is the target guarded (Cloudflare/Akamai)? -> Enable HumanType, BezierMouse, and Stealth Scripts.
|
||||||
Reference in New Issue
Block a user