🎭 Playwright Automation — Playwright 自动化

v1.0.0

Manikantasai Playwright 自动化工具。

0· 1.0k·3 当前·3 累计
by @manikantasai1987 (Manikantasai1987)·MIT-0
下载技能包
License
MIT-0
最后更新
2026/4/13
0
安全扫描
VirusTotal
可疑
查看报告
OpenClaw
可疑
medium confidence
The skill's Playwright instructions are plausible for browser automation, but internal inconsistencies (Node vs Python examples and mismatched declared requirements/install metadata) and the fact it instructs reading/writing local files merit caution before installing or running.
安全有层次,运行前请审查代码。

License

MIT-0

可自由使用、修改和再分发,无需署名。

运行时依赖

无特殊依赖

版本

latestv1.0.02026/2/9

Initial release of manikantasai-playwright-automation. - Provides direct Playwright API access for robust browser automation. - Supports navigation, interaction, data extraction, screenshots, PDFs, video recording, and complex workflows. - Includes best practices, usage patterns, and advanced features for Playwright automation. - Setup instructions, code examples, and troubleshooting tips included for Linux, macOS, and Windows. - More reliable approach than MCP-based solutions.

可疑

安装命令

点击复制
官方npx clawhub@latest install manikantasai-playwright-automation
🇨🇳 镜像加速npx clawhub@latest install manikantasai-playwright-automation --registry https://cn.longxiaskill.com

技能文档

Direct Playwright API for reliable browser automation without MCP complexity.

Installation

# Install Playwright
npm install -g playwright

# Install browsers (one-time, ~100MB each) npx playwright install chromium # Optional: npx playwright install firefox npx playwright install webkit

# For system dependencies on Ubuntu/Debian: sudo npx playwright install-deps chromium

Quick 开始

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

(async () => { const browser = await chromium.launch({ headless: true }); const page = await browser.newPage(); await page.goto('https://example.com'); await page.screenshot({ path: 'screenshot.png' }); await browser.close(); })();

Best Practices

1. 使用 Locators (Auto-waiting)

// ✅ GOOD: Uses auto-waiting and retries
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Username').fill('user');
await page.getByPlaceholder('Search').fill('query');

// ❌ BAD: May fail if element not ready await page.click('#submit');

2. Prefer 用户-Facing Attributes

// ✅ GOOD: Resilient to DOM changes
await page.getByRole('heading', { name: 'Welcome' });
await page.getByText('Sign in');
await page.getByTestId('login-button');

// ❌ BAD: Brittle CSS selectors await page.click('.btn-primary > div:nth-child(2)');

3. Handle Dynamic Content

// Wait for network idle
await page.goto('https://spa-app.com', { waitUntil: 'networkidle' });

// Wait for specific element await page.waitForSelector('.results-loaded'); await page.waitForFunction(() => document.querySelectorAll('.item').length > 0);

4. 使用 Contexts 对于 Isolation

// Each context = isolated session (cookies, storage)
const context = await browser.newContext();
const page = await context.newPage();

// Multiple pages in one context const page2 = await context.newPage();

5. Network Interception

// Mock API responses
await page.route('/api/users', route => {
  route.fulfill({
    status: 200,
    body: JSON.stringify({ users: [] })
  });
});

// Block resources await page.route('/.{png,jpg,css}', route => route.abort());

Common Patterns

表单 Automation

// Fill form
await page.goto('https://example.com/login');
await page.getByLabel('Username').fill('myuser');
await page.getByLabel('Password').fill('mypass');
await page.getByRole('button', { name: 'Sign in' }).click();

// Wait for navigation/result await page.waitForURL('/dashboard'); await expect(page.getByText('Welcome')).toBeVisible();

Data Extraction

// Extract table data
const rows = await page.$$eval('table tr', rows =>
  rows.map(row => ({
    name: row.querySelector('td:nth-child(1)')?.textContent,
    price: row.querySelector('td:nth-child(2)')?.textContent
  }))
);

// Extract with JavaScript evaluation const data = await page.evaluate(() => { return Array.from(document.querySelectorAll('.product')).map(p => ({ title: p.querySelector('.title')?.textContent, price: p.querySelector('.price')?.textContent })); });

Screenshots & PDFs

// Full page screenshot
await page.screenshot({ path: 'full.png', fullPage: true });

// Element screenshot await page.locator('.chart').screenshot({ path: 'chart.png' });

// PDF (Chromium only) await page.pdf({ path: 'page.pdf', format: 'A4', printBackground: true });

Video Recording

const context = await browser.newContext({
  recordVideo: {
    dir: './videos/',
    size: { width: 1920, height: 1080 }
  }
});
const page = await context.newPage();

// ... do stuff ...

await context.close(); // Video saved automatically

Mobile Emulation

const context = await browser.newContext({
  viewport: { width: 375, height: 667 },
  userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0)',
  isMobile: true,
  hasTouch: true
});

Authentication

// Method 1: HTTP Basic Auth
const context = await browser.newContext({
  httpCredentials: { username: 'user', password: 'pass' }
});

// Method 2: Cookies await context.addCookies([ { name: 'session', value: 'abc123', domain: '.example.com', path: '/' } ]);

// Method 3: Local Storage await page.evaluate(() => { localStorage.setItem('token', 'xyz'); });

// Method 4: Reuse auth state await context.storageState({ path: 'auth.json' }); // Later: await browser.newContext({ storageState: 'auth.json' });

Advanced Features

File 上传/下载

// Upload
await page.setInputFiles('input[type="file"]', '/path/to/file.pdf');

// Download const [download] = await Promise.all([ page.waitForEvent('download'), page.click('a[download]') ]); await download.saveAs('/path/to/save/' + download.suggestedFilename());

Dialogs Handling

page.on('dialog', dialog => {
  if (dialog.type() === 'alert') dialog.accept();
  if (dialog.type() === 'confirm') dialog.accept();
  if (dialog.type() === 'prompt') dialog.accept('My answer');
});

Frames & Shadow DOM

// Frame by name
const frame = page.frame('frame-name');
await frame.click('button');

// Frame by locator const frame = page.frameLocator('iframe').first(); await frame.getByRole('button').click();

// Shadow DOM await page.locator('my-component').locator('button').click();

Tracing (Debug)

await context.tracing.start({ screenshots: true, snapshots: true });

// ... run tests ...

await context.tracing.stop({ path: 'trace.zip' }); // View at https://trace.playwright.dev

Configuration Options

const browser = await chromium.launch({
  headless: true,        // Run without UI
  slowMo: 50,           // Slow down by 50ms (for debugging)
  devtools: false,      // Open DevTools
  args: ['--no-sandbox', '--disable-setuid-sandbox'] // Docker/Ubuntu
});

const context = await browser.newContext({ viewport: { width: 1920, height: 1080 }, locale: 'ru-RU', timezoneId: 'Europe/Moscow', geolocation: { latitude: 55.7558, longitude: 37.6173 }, permissions: ['geolocation'], userAgent: 'Custom Agent', bypassCSP: true, // Bypass Content Security Policy });

错误 Handling

// Retry with timeout
try {
  await page.getByRole('button', { name: 'Load' }).click({ timeout: 10000 });
} catch (e) {
  console.log('Button not found or not clickable');
}

// Check if element exists const hasButton = await page.getByRole('button').count() > 0;

// Wait with custom condition await page.waitForFunction(() => document.querySelectorAll('.loaded').length >= 10 );

Sudoers Setup

For Playwright browser installation:

# /etc/sudoers.d/playwright
username ALL=(root) NOPASSWD: /usr/bin/npx playwright install-deps 
username ALL=(root) NOPASSWD: /usr/bin/npx playwright install *

References

数据来源:ClawHub ↗ · 中文优化:龙虾技能库