内容
# 机器人合规抓取工作流 — MCP 服务器
一个 MCP 服务器,用于在有文档记录的 `robots.txt` 合规性、明确的用户确认计划和准备好加载到数据库的单个数据对象之间进行 AI 代理网页抓取。
## ⚠️ 本次认证的内容和不认证的内容
`check_robots_compliance` 产生 **可验证的技术证据**,证明某个网站的 `robots.txt` 允许特定的用户代理在给定的路径上访问:原始适用的指令行、`robots.txt` 文件的 SHA-256 哈希值、HTTP 状态和 UTC 获取时间戳。它 **不** 认证合法性。`robots.txt` 是一个自愿的约定(RFC 9309),不是合同或许可证。服务条款、版权和数据保护法律(GDPR/CCPA)独立适用 — 每个工具响应都重复此免责声明,以便其随数据一起传递。
## 架构
服务器不驱动浏览器。AI 代理(例如,带有 Chrome 中 Claude 工具的 Claude)执行服务器门户之间的动态导航:
```
用户请求
│
▼
[1] check_robots_compliance ──► 裁决 + 证据(check_id)
│ └── 拒绝? 停止。
▼
代理在聊天中与用户确认:
导航步骤 · 抓取范围 · 排除项 ·
最大页面数 · 速率限制 · 输出格式 · 输出模式
│
▼
[2] create_scrape_plan(check_id, ..., user_confirmed=True) ──► plan_id
│ (拒绝未确认的计划、拒绝的裁决、未知的 check_ids;
│ 强制执行 robots.txt Crawl-delay 作为速率限制底线)
▼
代理使用浏览器工具(Chrome 中的 Claude)执行计划:
导航 → 等待 JS 渲染 → 提取字段 → 分页
│
▼
[3] package_results(plan_id, records) ──► 一个数据对象:
{ 数据,模式,来源{机器人证据,计划,页面},
验证问题,警告 }
```
## 安装和运行
```bash
pip install mcp httpx
python server.py # 标准输入输出传输
```
### Claude Desktop / Claude Code 配置
```json
{
"mcpServers": {
"robots-compliance-scraper": {
"command": "python",
"args": ["/绝对路径/to/server.py"]
}
}
}
```
## 工具
### `check_robots_compliance(site_url, user_agent="ClaudeBot", target_paths=["/"])`
获取 `/robots.txt`,根据 RFC 9309 评估每个目标路径,并返回:
`verdict`(`allowed` | `partially_allowed` | `denied` | `allowed_no_robots` | `indeterminate`),每个路径的结果,原始适用的用户代理组、`robots.txt` 文件的 SHA-256 哈希值,任何 `Crawl-delay` 和法律免责声明。
### `create_scrape_plan(check_id, navigation_steps, scope_description, output_format, output_schema, max_pages, min_delay_seconds, user_confirmed, exclusions)`
门控:需要一个通过的 `check_id` 和 `user_confirmed=True`。代理必须在设置该标志之前向用户展示完整的计划并获得明确的批准。`output_format` 每次运行都会选择:`json_object`、`jsonl` 或 `sql_rows`。有效的延迟是 `max(min_delay_seconds, Crawl-delay)`。
### `package_results(plan_id, records, pages_visited, warnings)`
根据计划的模式验证记录(报告每个记录缺少/意外的字段),渲染选择的格式,并返回一个单独的 `scrape_result_v1` 对象,该对象嵌入了合规证据和计划作为来源 — 加载到您的数据库并在下游转换。
## 示例数据对象(缩略)
```json
{
"object_type": "scrape_result_v1",
"record_count": 2,
"output_format": "sql_rows",
"data": { "records": [...], "columns": ["price", "title"], "rows": [[1.5, "A"], ...] },
"provenance": {
"site_url": "https://example.com",
"pages_visited": ["https://example.com/js/"],
"scrape_plan": { "plan_id": "plan_ab12...", "navigation_steps": [...], ... },
"robots_compliance": {
"verdict": "allowed",
"evidence": {
"applicable_group_verbatim": ["User-agent: *", "Allow: /"],
"robots_txt_sha256": "05a5baaa...",
"crawl_delay_seconds": 5.0
}
}
},
"validation_issues": [],
"legal_disclaimer": "robots.txt 合规性是一个技术/礼仪信号,而不是法律同意 ..."
}
```
## 每个计划中内置的代理礼仪
- 遵守 `Crawl-delay`;默认底线 2 秒的页面加载间隔
- 每个运行的硬页面上限(`max_pages`,默认为 25)
- 没有登录、绕过付费墙或解决 CAPTCHA
- 在任何导航之前,用户确认范围 + 排除项