关于 scraper-builder
scraper-builder 是一项面向开发者的技能,可生成基于 Playwright 和 TypeScript 的网站专用爬虫项目。它采用 PageObject 组织代码,并提供 Zod 数据验证和 Docker 配置。
主要功能
- 01使用 Playwright 和 TypeScript 生成爬虫
- 02按页面组织 PageObject
- 03使用 Zod 验证提取数据
- 04生成支持 Docker 的项目
- 05通过 agent-browser 分析选择器
适用场景
- 01为特定网站创建爬虫
- 02根据页面结构生成 PageObject
- 03提取带分页的数据
- 04在 Docker 中运行爬虫
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jwynia/ agent-skills --skill scraper-builder安装后在 Claude Code 中输入/scraper-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/configs/docker-compose.yml.mddockerfile.mdpackage.json.mdplaywright.config.ts.mdtsconfig.json.mdassets/examples/ecommerce-scraper.mdmulti-page-pagination.mdassets/templates/base-page.ts.mdcomponent.ts.mddata-schema.ts.mdpage-object.ts.mdscraper-runner.ts.mddata/selector-patterns.jsonsite-archetypes.jsonreferences/agent-browser-workflow.mdanti-patterns.mddocker-setup.mdpageobject-pattern.mdplaywright-selectors.mdscripts/generate-page-object.tsscaffold-scraper-project.ts详细介绍
爬虫构建器
使用 Playwright 和 TypeScript,通过 PageObject 模式生成完整、可运行的网页爬虫项目。此技能可生成针对特定网站的爬虫,支持类型化数据提取、Docker 部署,以及可选的 agent-browser 集成,用于自动分析网站。
使用此技能的场景
在以下情况下使用此技能:
- 构建用于数据提取的特定网站爬虫
- 为目标网站生成 PageObject 类
- 搭建支持 Docker 的完整爬虫项目
- 使用 agent-browser 分析网站并自动生成选择器
- 创建可复用的抓取组件(分页、数据表格)
在以下情况下不要使用此技能:
- 构建 API 客户端(直接使用 HTTP 客户端库)
- 编写 QA/E2E 测试套件(使用 Playwright 测试运行器和以测试为核心的模式)
- 大规模爬取或抓取整个域名(使用 Crawlee 或 Scrapy)
- 抓取需要绕过身份验证或破解 CAPTCHA 的网站
核心原则
1. PageObject 封装
目标网站上的每个页面都对应一个 PageObject 类。定位器在构造函数中定义,抓取逻辑放在方法中。页面对象不包含断言或业务逻辑,只负责提取并返回数据。
2. 选择器的稳定性
优先按以下顺序选择定位器:data-testid > id > 语义化 HTML(role、aria-label)> 结构化 CSS 类 > 文本内容。避免使用位置选择器(nth-child)和依赖布局的路径。完整的优先级层级请参阅 references/playwright-selectors.md。
3. 组合优于继承
可复用的 UI 模式(分页、数据表格、搜索栏)应建模为组件类,页面对象通过属性组合这些组件。只有 BasePage 使用继承,其余部分均采用组合。
4. 类型化数据提取
所有抓取的数据都通过 Zod 模式进行验证。这能在提取时发现选择器漂移(网站更改标记时),而不是等到下游才发现。请参阅 assets/templates/data-schema.ts.md。
5. Docker 优先部署
生成的项目包含使用 Microsoft 官方 Playwright 镜像的 Dockerfile,以及用于挂载输出数据和调试截图的 docker-compose.yml。这能确保不同机器上的浏览器环境保持一致。
生成模式
模式 1:Agent-Browser 分析
使用 agent-browser 导航目标网站、捕获无障碍树快照,并自动发现选择器。当 Agent 能够访问 agent-browser CLI 时,优先使用此模式。
**前提条件:**如果尚未安装 agent-browser,请先将其添加为技能:
npx skills add vercel-labs/agent-browser
工作流:
# 1. Open the target page
agent-browser open https://example.com/products
# 2. Capture interactive snapshot with element references
agent-browser snapshot -i --json > snapshot.json
# 3. Capture scoped sections for focused analysis
agent-browser snapshot -i --json -s "main" > main-content.json
agent-browser snapshot -i --json -s "nav" > navigation.json
# 4. Test dynamic behavior (pagination, load-more)
agent-browser click @e3
agent-browser wait --load networkidle
agent-browser snapshot -i --json > after-click.json
# 5. Close when done
agent-browser close
Agent 如何处理快照:
- 解析元素引用(
@e1、@e2等)及其角色 - 按语义用途对元素分组(导航、数据显示、表单、操作)
- 将数据元素映射到字段(标题、价格、图片等)
- 使用发现的选择器生成 PageObject 类
- 识别分页和动态加载模式
完整的工作流参考请参阅 references/agent-browser-workflow.md。
模式 2:手动描述
用户描述目标网站的页面结构,Agent 将其映射到页面对象。Agent 会提出以下结构化问题:
- 要抓取哪些页面? — URL 列表或页面类型
- 要提取哪些数据? — 每个页面的字段名称和预期类型
- 数据如何分页? — 编号分页、加载更多、无限滚动或单页
- 已知哪些选择器? — 用户已知的 CSS 选择器、data-testid 值或 XPath
随后 Agent 会:
- 将描述与
data/site-archetypes.json中的网站类型进行匹配 - 提出页面对象映射方案,列出类名和职责
- 在用户确认方案后生成代码
模式 3:完整项目脚手架
使用脚手架脚本,一次性生成完整的可运行项目:
deno run --allow-read --allow-write scripts/scaffold-scraper-project.ts \
--name "my-scraper" \
--url "https://example.com" \
--pages "ProductListing,ProductDetail" \
--fields "title,price,image_url,description"
这会生成一个包含所有源文件、配置、Docker 设置以及可直接运行的入口点的项目。完整选项请参阅“脚本参考”部分。
快速参考
| 类别 | 方案 | 详情 |
|---|---|---|
| 框架 | Playwright | 使用 playwright 包,而非 @playwright/test |
| 语言 | TypeScript | 严格模式,ES2022 目标 |
| 模式 | PageObject | 每个页面一个类,组合组件 |
| 选择器 | 稳健 | data-testid > id > role > CSS 类 > 文本 |
| 等待策略 | 自动等待 | Playwright 内置功能,导航时另加 networkidle |
| 验证 | Zod | 为每个页面对象的输出类型定义一个 Schema |
| 输出 | JSON + CSV | 可通过存储工具配置 |
| Docker | 官方镜像 | mcr.microsoft.com/playwright:v1.48.0-jammy |
| 重试 | 指数退避 | 默认尝试 3 次,可配置 |
| 截图 | 出错时 | 保存到 screenshots/ 以便调试 |
生成流程
生成爬虫时请遵循以下步骤:
步骤 1:收集需求
询问用户:
- 目标网站 URL
- 要提取的数据字段
- 预期的页面/项目数量
- 首选输出格式(JSON、CSV 或两者)
- 是否需要 Docker 部署
步骤 2:分析网站
使用模式 1(agent-browser)或模式 2(手动描述)了解:
- 页面结构和导航流程
- 数据元素的位置和选择器策略
- 分页或无限滚动模式
- 动态内容加载行为
步骤 3:设计页面对象映射
制定计划,列出:
- 每个 PageObject 类及其 URL 模式
- 所需的组件类(Pagination、DataTable 等)
- 每个页面的数据 Schema 字段和类型
- 爬虫在页面之间的导航流程
步骤 4:展示计划
生成代码前,向用户展示页面对象映射。包含类名、字段名和执行流程。等待用户确认。
步骤 5:生成代码
以 assets/templates/ 中的模板为基础:
base-page.ts.md— BasePage 抽象类page-object.ts.md— 网站专用页面对象component.ts.md— 可复用组件scraper-runner.ts.md— 编排器data-schema.ts.md— Zod 验证 Schema
步骤 6:交付
提供完整项目,包括:
- 所有源文件
assets/configs/中的配置文件- 说明如何运行项目的 README
- Docker 设置(除非明确排除)
代码模式
BasePage
提供 navigate()、waitForPageLoad()、screenshot() 和 getText() 辅助方法的抽象类。所有页面对象都继承此类。
export abstract class BasePage {
constructor(protected readonly page: Page) {}
async navigate(url: string): Promise<void> { /* ... */ }
async screenshot(name: string): Promise<void> { /* ... */ }
}
参见:assets/templates/base-page.ts.md
PageObject
网站专用类,包含作为只读属性的定位器、返回类型化数据的抓取方法,以及用于多页面流程的导航方法。
export class ProductListingPage extends BasePage {
readonly productCards: Locator;
readonly nextButton: Locator;
async scrapeProducts(): Promise<Product[]> { /* ... */ }
async goToNextPage(): Promise<boolean> { /* ... */ }
}
参见:assets/templates/page-object.ts.md
Component
可复用的 UI 模式(Pagination、DataTable),接收父级定位器范围,并提供提取方法。
export class Pagination {
constructor(private page: Page, private scope: Locator) {}
async hasNextPage(): Promise<boolean> { /* ... */ }
async goToNext(): Promise<void> { /* ... */ }
}
参见:assets/templates/component.ts.md
ScraperRunner
用于启动浏览器、创建页面对象、遍历页面、收集数据、使用 Schema 验证数据并写入输出的编排器。
export class SiteScraper {
async run(): Promise<void> {
const browser = await chromium.launch();
const page = await browser.newPage();
// navigate, scrape, validate, write
}
}
参见:assets/templates/scraper-runner.ts.md
DataSchema
用于验证抓取记录的 Zod Schema,可在提取时发现选择器变化和格式错误的数据。
export const ProductSchema = z.object({
title: z.string().min(1),
price: z.number().positive(),
});
参见:assets/templates/data-schema.ts.md
反模式
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 单体爬虫 | 所有抓取逻辑都放在一个文件中 | 按页面拆分为 PageObject 类 |
| 固定等待 | 使用 setTimeout/固定延迟 | 使用 Playwright 自动等待和 networkidle |
| 未验证的流程 | 未对输出进行架构验证 | 为每种数据类型添加 Zod 架构 |
| 选择器碰运气 | 使用脆弱的位置选择器 | 使用可靠的选择器层级 |
| 静默失败 | 吞掉错误且不记录日志 | 记录失败并保存调试截图 |
| 不限速的爬虫 | 请求之间没有延迟 | 添加可配置的请求延迟 |
| 硬编码配置 | URL 和选择器写在代码中 | 使用环境变量和配置文件 |
| 没有重试逻辑 | 每个请求只尝试一次 | 实现指数退避 |
请参阅 references/anti-patterns.md,了解包含示例和修复方案的扩展目录。
脚本参考
scaffold-scraper-project.ts
生成完整的爬虫项目:
deno run --allow-read --allow-write scripts/scaffold-scraper-project.ts [options]
Options:
--name <name> Project name (required)
--path <path> Target directory (default: ./)
--url <url> Target site base URL
--pages <pages> Comma-separated page names (e.g., ProductListing,ProductDetail)
--fields <fields> Comma-separated data fields (e.g., title,price,rating)
--no-docker Skip Docker setup
--no-validation Skip Zod validation setup
--json Output as JSON
-h, --help Show help
Examples:
# Scaffold a product scraper
deno run --allow-read --allow-write scripts/scaffold-scraper-project.ts \
--name "shop-scraper" --url "https://shop.example.com" \
--pages "ProductListing,ProductDetail" --fields "title,price,image_url"
# Minimal scraper without Docker
deno run --allow-read --allow-write scripts/scaffold-scraper-project.ts \
--name "blog-scraper" --no-docker
generate-page-object.ts
为现有项目生成单个 PageObject 类:
deno run --allow-read --allow-write scripts/generate-page-object.ts [options]
Options:
--name <name> Class name (required)
--url <url> Page URL (for documentation comment)
--fields <fields> Comma-separated data fields
--selectors <json> JSON map of field to selector
--with-pagination Include pagination methods
--output <path> Output file path (default: stdout)
--json Output as JSON
-h, --help Show help
Examples:
# Generate a page object with known selectors
deno run --allow-read --allow-write scripts/generate-page-object.ts \
--name "ProductListing" --url "https://shop.example.com/products" \
--fields "title,price,rating" \
--selectors '{"title":".product-title","price":".product-price","rating":".star-rating"}' \
--with-pagination --output src/pages/ProductListingPage.ts
# Quick generation to stdout
deno run --allow-read scripts/generate-page-object.ts \
--name "SearchResults" --fields "title,url,snippet"
模板和参考资料
模板(assets/templates/)
| 模板 | 用途 |
|---|---|
base-page.ts.md | 抽象 BasePage,包含导航、截图和文本辅助方法 |
page-object.ts.md | 针对特定网站的页面对象,包含定位器和抓取方法 |
component.ts.md | 可复用组件:Pagination、DataTable |
scraper-runner.ts.md | 协调器:启动浏览器、迭代、收集和输出 |
data-schema.ts.md | 用于验证抓取数据的 Zod 架构 |
配置(assets/configs/)
| 配置 | 用途 |
|---|---|
dockerfile.md | 使用官方 Playwright 镜像的多阶段 Dockerfile |
docker-compose.yml.md | 带有 data/screenshots 卷挂载的服务 |
tsconfig.json.md | 使用 ES2022 目标的严格 TypeScript 配置 |
package.json.md | playwright、zod、tsx 依赖项 |
playwright.config.ts.md | 面向爬虫的 Playwright 配置 |
参考资料(references/)
| 参考资料 | 用途 |
|---|---|
pageobject-pattern.md | 针对抓取任务调整的 PageObject 模式 |
playwright-selectors.md | 选择器策略和可靠性层级 |
docker-setup.md | Docker 配置和部署 |
agent-browser-workflow.md | Agent-browser 分析工作流 |
anti-patterns.md | 扩展反模式目录 |
示例(assets/examples/)
| 示例 | 用途 |
|---|---|
ecommerce-scraper.md | 完整的多页面商品爬虫演练 |
multi-page-pagination.md | 分页处理策略 |
数据文件(data/)
| 文件 | 用途 |
|---|---|
selector-patterns.json | 按 UI 元素类型整理的常用选择器 |
site-archetypes.json | 网站结构原型及其典型页面和字段 |
交互示例
用户:“我需要为一家在线书店编写爬虫。我想从目录页面获取书名、作者、价格和评分。”
Agent 工作流:
- 检查
site-archetypes.json— 匹配ecommerce原型 - 提出页面对象映射:
BookListingPage— 带分页的目录BookDetailPage— 单本书的页面(如果需要抓取详情)Pagination组件 — 共享的分页处理器
- 展示计划和字段映射:
title→[itemprop="name"]或.book-titleauthor→[itemprop="author"]或.book-authorprice→[itemprop="price"]或.pricerating→.star-rating或[data-rating]
- 确认后,使用脚手架脚本或手动生成代码
- 提供包含 Docker 配置和
Book类型 Zod 架构的项目
集成
此技能连接到:
- typescript-best-practices — 生成代码中使用的 TypeScript 编码模式
- devcontainer — 为生成的项目设置开发容器
- agent-browser — 网站分析和选择器发现(外部工具)
你不会做什么
此技能不会:
- 绕过身份验证或登录墙
- 解决 CAPTCHA 或机器人检测
- 生成仅包含 JavaScript 的输出(始终使用 TypeScript)
- 生成遍历整个域名的爬虫
- 创建违反 robots.txt 的抓取工具
- 处理受速率限制的 API(使用 HTTP 客户端进行 API 工作)
- 生成测试套件(使用 Playwright 测试模式进行 QA)