mcpField
P
playwright-web-scraper

playwright-web-scraper

github.com/dawiddutoit数据与数据库2392 次安装40 周前更新
代码仓库

关于 playwright-web-scraper

Playwright Web Scraper 是使用 Playwright MCP 浏览器工具从多个网页提取结构化数据的技能,涵盖 URL 与 robots.txt 检查、限速爬取、错误处理,以及导出为 JSON、CSV 或 Markdown。

主要功能

  1. 01验证 URL 和 robots.txt
  2. 02限速爬取多个网页
  3. 03使用 JavaScript 提取数据
  4. 04处理网络错误与限流
  5. 05输出 JSON、CSV 和 Markdown

适用场景

  1. 01采集多个页面的商品列表
  2. 02提取表格或页面结构化字段
  3. 03转换抓取数据以供分析

MCP 相关

它使用 Playwright MCP 浏览器工具浏览页面、检查内容并提取数据。文档未说明其提供 MCP 服务。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dawiddutoit/custom-claude --skill playwright-web-scraper

安装后在 Claude Code 中输入/playwright-web-scraper确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
ethical-scraping.md
extraction-patterns.md
scripts/
process_results.py
validate_urls.py

详细介绍

Playwright 网页抓取

以尊重且合乎道德的爬取方式,从多个网页中提取结构化数据。

何时使用此技能

当需要从网站“抓取数据”“从页面提取信息”“收集网站数据”或“爬取多个页面”时使用。

请勿用于测试工作流(使用 playwright-e2e-testing)、监控错误(使用 playwright-console-monitor)或分析网络(使用 playwright-network-analyzer)。务必遵守 robots.txt 和速率限制。

快速开始

从电子商务网站抓取商品列表:

// 1. Validate URLs
python scripts/validate_urls.py urls.txt

// 2. Scrape pages with rate limiting
const results = [];
for (const url of urls) {
  await browser_navigate({ url });
  await browser_wait_for({ time: Math.random() * 2 + 1 }); // 1-3s delay

  const data = await browser_evaluate({
    function: `
      Array.from(document.querySelectorAll('.product')).map(el => ({
        title: el.querySelector('.title')?.textContent?.trim(),
        price: el.querySelector('.price')?.textContent?.trim(),
        url: el.querySelector('a')?.getAttribute('href')
      }))
    `
  });

  results.push(...data);
}

// 3. Process results
python scripts/process_results.py scraped.json -o products.csv

目录

  1. 核心工作流
  2. 速率限制策略
  3. URL 验证
  4. 数据提取
  5. 错误处理
  6. 结果处理
  7. 支持文件
  8. 预期结果

核心工作流

步骤 1:准备 URL 列表

创建一个包含待抓取 URL 的文本文件(每行一个):

https://example.com/products?page=1
https://example.com/products?page=2
https://example.com/products?page=3

验证 URL 并检查是否符合 robots.txt 规定:

python scripts/validate_urls.py urls.txt --user-agent "MyBot/1.0"
步骤 2:初始化抓取会话

导航到网站并拍摄快照,以了解页面结构:

await browser_navigate({ url: firstUrl });
await browser_snapshot();

使用快照确定用于提取数据的 CSS 选择器。

步骤 3:实现限速爬取

在请求之间加入随机延迟(至少 1-3 秒):

const results = [];

for (const url of urlList) {
  // Navigate to page
  await browser_navigate({ url });

  // Wait for content to load
  await browser_wait_for({ text: 'Expected content marker' });

  // Add respectful delay (1-3 seconds)
  const delay = Math.random() * 2 + 1;
  await browser_wait_for({ time: delay });

  // Extract data
  const pageData = await browser_evaluate({
    function: `/* extraction code */`
  });

  results.push(...pageData);

  // Check console for errors/warnings
  const console = await browser_console_messages();
  // Monitor for rate limit warnings
}
步骤 4:提取结构化数据

使用 browser_evaluate 和 JavaScript 提取数据:

const data = await browser_evaluate({
  function: `
    try {
      return Array.from(document.querySelectorAll('.item')).map(el => ({
        title: el.querySelector('.title')?.textContent?.trim(),
        price: el.querySelector('.price')?.textContent?.trim(),
        rating: el.querySelector('.rating')?.textContent?.trim(),
        url: el.querySelector('a')?.getAttribute('href')
      })).filter(item => item.title && item.price); // Filter incomplete records
    } catch (e) {
      console.error('Extraction failed:', e);
      return [];
    }
  `
});

有关全面的数据提取模式,请参阅 references/extraction-patterns.md。

步骤 5:处理错误和速率限制

监控速率限制指标:

// Check HTTP responses via browser_network_requests
const requests = await browser_network_requests();
const rateLimited = requests.some(r => r.status === 429 || r.status === 503);

if (rateLimited) {
  // Back off exponentially
  await browser_wait_for({ time: 10 }); // Wait 10 seconds
  // Retry or skip
}

// Check console for blocking messages
const console = await browser_console_messages({ pattern: 'rate limit|blocked|captcha' });
if (console.length > 0) {
  // Handle blocking
}
步骤 6:汇总并存储结果

将结果保存到 JSON 文件:

// In your scraping script
fs.writeFileSync('scraped.json', JSON.stringify({ results }, null, 2));

处理结果并转换为所需格式:

# View statistics
python scripts/process_results.py scraped.json --stats

# Convert to CSV
python scripts/process_results.py scraped.json -o output.csv

# Convert to Markdown table
python scripts/process_results.py scraped.json -o output.md

速率限制策略

最短延迟

务必在请求之间加入延迟:

  • 普通网站:1-3 秒(随机)
  • 流量较大的网站:3-5 秒
  • 小型网站:5-10 秒
  • 出错后:指数退避(5 秒、10 秒、20 秒、40 秒)
实现方式
// Random delay between 1-3 seconds
const randomDelay = () => Math.random() * 2 + 1;
await browser_wait_for({ time: randomDelay() });

// Exponential backoff after rate limit
let backoffSeconds = 5;
for (let retry = 0; retry < 3; retry++) {
  try {
    await browser_navigate({ url });
    break; // Success
  } catch (e) {
    await browser_wait_for({ time: backoffSeconds });
    backoffSeconds *= 2; // Double delay each retry
  }
}
自适应速率限制

根据响应调整延迟:

响应代码操作
200 OK按正常延迟继续(1-3 秒)
429 Too Many Requests将延迟增加到 10 秒,然后重试
503 Service Unavailable等待 60 秒,然后重试
403 Forbidden停止抓取此域名

有关详细的速率限制策略,请参阅 references/ethical-scraping.md。

URL 验证

抓取前使用 validate_urls.py 确保符合规定:

# Basic validation
python scripts/validate_urls.py urls.txt

# Check robots.txt with specific user agent
python scripts/validate_urls.py urls.txt --user-agent "MyBot/1.0"

# Strict mode (exit on any invalid/disallowed URL)
python scripts/validate_urls.py urls.txt --strict

输出包括:

  • URL 格式验证
  • 域名分组
  • robots.txt 合规性检查
  • 汇总统计

数据提取

基本模式
// Single page extraction
const data = await browser_evaluate({
  function: `
    Array.from(document.querySelectorAll('.item')).map(el => ({
      field1: el.querySelector('.selector1')?.textContent?.trim(),
      field2: el.querySelector('.selector2')?.getAttribute('href')
    }))
  `
});
分页模式
let hasMore = true;
let page = 1;

while (hasMore) {
  await browser_navigate({ url: `${baseUrl}?page=${page}` });
  await browser_wait_for({ time: randomDelay() });

  const pageData = await browser_evaluate({ function: extractionCode });
  results.push(...pageData);

  // Check for next page
  hasMore = await browser_evaluate({
    function: `document.querySelector('.next:not(.disabled)') !== null`
  });

  page++;
}

有关以下内容,请参阅 references/extraction-patterns.md:

  • 高级选择器
  • 数据清理模式
  • 表格提取
  • JSON-LD 提取
  • Shadow DOM 访问

错误处理

网络错误
try {
  await browser_navigate({ url });
} catch (e) {
  console.error(`Failed to load ${url}:`, e);
  failedUrls.push(url);
  continue; // Skip to next URL
}
内容验证
const data = await browser_evaluate({ function: extractionCode });

if (!data || data.length === 0) {
  console.warn(`No data extracted from ${url}`);
  // Log for manual review
}

// Validate data structure
const validData = data.filter(item =>
  item.title && item.price // Ensure required fields exist
);
监控指标

检查是否存在拦截或错误:

// Monitor console
const console = await browser_console_messages({
  pattern: 'error|rate|limit|captcha',
  onlyErrors: true
});

if (console.length > 0) {
  console.log('Warnings detected:', console);
}

// Monitor network
const requests = await browser_network_requests();
const errors = requests.filter(r => r.status >= 400);

结果处理

查看统计信息
python scripts/process_results.py scraped.json --stats

输出:

📊 Statistics:
  Total records: 150
  Fields (5): title, price, rating, url, image
  Sample record: {...}
转换格式
# To CSV
python scripts/process_results.py scraped.json -o products.csv

# To JSON (compact)
python scripts/process_results.py scraped.json -o products.json --compact

# To Markdown table
python scripts/process_results.py scraped.json -o products.md
合并统计与格式转换
python scripts/process_results.py scraped.json -o products.csv --stats

支持文件

脚本
  • scripts/validate_urls.py - 验证 URL 列表、检查 robots.txt 合规性并按域名分组
  • scripts/process_results.py - 将抓取的 JSON 转换为 CSV/JSON/Markdown,并查看统计信息
参考资料
  • references/ethical-scraping.md - 关于速率限制、robots.txt、错误处理和监控的综合指南
  • references/extraction-patterns.md - 用于数据提取、选择器、分页和表格的 JavaScript 模式

预期结果

成功抓取
✅ Validated 50 URLs
✅ Scraped 50 pages in 5 minutes (6 req/min)
✅ Extracted 1,250 products
✅ Zero rate limit errors
✅ Exported to products.csv (1,250 rows)
错误处理
⚠️  Validated 50 URLs (2 disallowed by robots.txt)
✅ Scraped 48 pages
⚠️  3 pages returned no data (logged for review)
✅ Extracted 1,100 products
⚠️  1 rate limit warning (backed off successfully)
✅ Exported to products.csv (1,100 rows)
速率限制检测
❌ Rate limited after 20 pages (429 responses)
✅ Backed off exponentially (5s → 10s → 20s)
✅ Resumed scraping successfully
✅ Extracted 450 products from 25 pages

预期收益

指标之前之后
设置时间30-45 分钟5-10 分钟
速率限制错误常见罕见
robots.txt 违规可能发生可避免
数据格式转换手动自动化
错误检测手动审查自动监控

成功指标

  • 成功率 > 95%(成功抓取的页面)
  • 速率限制错误 < 5% 的请求
  • 有效数据率 > 90%(完整记录)
  • 抓取速度 6-12 次请求/分钟(礼貌爬取)

要求

工具
  • Playwright MCP 浏览器工具
  • Python 3.8+(用于脚本)
  • 仅使用标准库(脚本不依赖外部依赖项)
知识
  • 基本 CSS 选择器
  • 用于数据提取的 JavaScript
  • 了解 HTTP 状态码
  • 了解网页抓取伦理

应避免的危险做法

  • ❌ 未检查 robots.txt 就进行抓取
  • ❌ 请求之间没有延迟(对服务器发起高频请求)
  • ❌ 忽略 429/503 响应码
  • ❌ 抓取个人/私人信息
  • ❌ 未监控控制台中的拦截消息
  • ❌ 抓取明确禁止此类行为的网站(查看 ToS)
  • ❌ 违反版权规定使用抓取的数据
  • ❌ 未正确处理分页(导致数据缺失)
  • ❌ 选择器写死且没有备用方案
  • ❌ 未验证提取的数据结构

注意事项

  • 默认采用礼貌爬取:至少延迟 1-3 秒,并根据网站响应进行调整
  • 务必先检查 robots.txt:抓取前使用 validate_urls.py
  • 监控控制台和网络:留意速率限制警告并调整延迟
  • 从小规模开始:先用 5-10 个 URL 测试,再扩展到数百个
  • 保存进度:逐步写入结果,以防中断
  • 遵守 ToS:有些网站在服务条款中禁止抓取
  • 使用描述性用户代理:清楚标识你的机器人
  • 妥善处理错误:记录失败以供手动审查,不要崩溃

评论

支持 Markdown