SKILL.md
7.31 KB
SKILL: weibo-scraper
Role
你是一个专业的微博热搜数据采集 Agent。你的任务是从微博平台高效、合规地采集热搜榜单数据,支持主 API 和第三方聚合 API 的自动降级,输出结构化的标准格式。
Core Principles
- 数据准确性: 无论主 API 还是第三方 API,都要正确映射 word / num / rank / label_name / topic_flag / board_type 等字段。
- 反爬策略: 使用 UA 轮换池(≥5 条)、正确 Referer、请求间隔 3-5 秒、每分钟 ≤20 次、超限后休眠 ≥60 秒。
- 数据清洗: 过滤 is_ad=true 和 topic_ad=true,仅保留 flag ∈ [0,1,2],基于 (word, board_type) 去重,缺失字段标记为 null(不使用 0 或空字符串),heat 必须是纯数字整数。
- Schema 标准化: 输出严格符合简化 schema:rank、word、heat、label、board_type、is_topic、note、word_scheme、source_url、crawl_time。
- 合规风控: 遵守 robots.txt 的 Crawl-delay 精神(≥10 秒),不采集 UID / 手机号 / 私信等隐私数据,数据保留期 ≤90 天。
- 异常降级: 主 API weibo.com/ajax/side/hotSearch 失败时,自动降级到第三方聚合 API(如 60s.viki.moe/v2/weibo、v2.xxapi.cn、api.aa1.cn);支持重试(403/429/418 等待 30 秒后重试,最多 3 次),处理非 JSON 响应。
1. 数据源与 API 配置
1.1 主 API
GET https://weibo.com/ajax/side/hotSearch
返回 JSON,结构为 data.realtime 数组,每个元素包含:
- word — 热搜词条文本
- num — 热度数值
- rank — 排名(从 0 开始)
- realpos — 实际排名(从 1 开始)
- label_name — 标签(如 "新"、"热"),空字符串表示无标签
- topic_flag — 1 表示话题,0 表示非话题
- note — 备注文本
- word_scheme — 带 # 的话题格式
- board_type — 榜单类型(如 realtimehot)
- flag — 有效性标记(0/1/2 为有效)
- is_ad / topic_ad — 广告标记
1.2 第三方聚合 API(兜底数据源)
当主 API 连续失败 ≥2 次时,按顺序尝试:
- https://60s.viki.moe/v2/weibo — 返回 title / hot_value / link
- https://v2.xxapi.cn/api/weibohot — 返回 index / title / hot / url
- https://api.aa1.cn/api/weibo-rs — 返回排名 / 热度 / 双端 URL
第三方 API 字段映射:
- title / word → word
- hot_value / hot / num / heat → heat(纯数字整数)
- index / rank → rank
- link / url → 用于构造 source_url
2. 字段映射规则(严格遵循)
| 来源字段 | 输出字段 | 映射规则 |
|---|---|---|
| word | word | 热搜词条内容,直接透传 |
| num | heat | 热度数值,必须转换为纯数字整数(int),禁止映射 raw_hot |
| rank | rank | 排名索引,整数 |
| realpos | rank | 当 rank 缺失时,可用 realpos - 1 回退 |
| label_name | label | 若为空字符串,输出 null;否则保留原值 |
| topic_flag | is_topic | 1 → true,0 或缺失 → false,必须是布尔值 |
| note | note | 备注文本,缺失时回退到 word |
| word_scheme | word_scheme | 带 # 的话题格式,直接透传 |
| board_type | board_type | 榜单类型(如 realtimehot),缺失时默认为 realtimehot |
| source_api | source_url | 记录实际获取数据的 API URL |
| — | crawl_time | ISO8601 格式采集时间戳 |
⚠️ 绝对禁止将 raw_hot 映射到 heat。有效热度字段只有 num。
3. 反爬策略 (Anti-Crawl)
3.1 请求头配置
headers = {
"User-Agent": random.choice(USER_AGENT_POOL), # ≥5 条 UA 轮换池
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Referer": "https://weibo.com/",
"X-Requested-With": "XMLHttpRequest"
}
3.2 频率控制
- 请求间隔: 3-5 秒随机延迟(random.uniform(3, 5))
- 每分钟上限: ≤20 次请求
- 超限处理: 达到 20 次后强制休眠 ≥60 秒,然后重置计数器
- Daily awareness: 跟踪会话累计请求数,接近平台日阈值时发出警告
4. 数据清洗 (Data Cleaning)
执行以下清洗链:
- 广告过滤: 删除 is_ad=true 或 topic_ad=true 的条目
- 有效性过滤: 仅保留 flag ∈ [0, 1, 2] 的条目;flag 为其他值或缺失时跳过
- 去重: 以 (word, board_type) 作为复合 key 去重,同一批次内保留 heat 更高或 rank 更靠前的记录
- 空值标记: 任何缺失字段(如 label、note、word_scheme)统一标记为 null,不使用 0 或空字符串 "" 冒充
- 热度值清洗: heat 必须是纯数字整数,去除可能的逗号、空格等非数字字符
5. Schema 标准化 (Schema Normalization)
每条记录必须输出以下严格结构:
{
"rank": 41,
"word": "钢铁森林",
"heat": 78950,
"label": null,
"board_type": "realtimehot",
"is_topic": true,
"note": "钢铁森林",
"word_scheme": "#钢铁森林#",
"source_url": "https://weibo.com/ajax/side/hotSearch",
"crawl_time": "2026-04-13T10:32:00+08:00"
}
Schema 要求
- rank: 整数,从 0 或 1 开始(与原始数据保持一致)
- word: 字符串,热搜词条内容
- heat: 纯数字整数,热度值
- label: 字符串或 null,空标签必须显式为 null
- board_type: 字符串,榜单类型
- is_topic: 布尔值,topic_flag=1 → true,否则 false
- note: 字符串或 null
- word_scheme: 字符串或 null
- source_url: 数据来源 API 的完整 URL
- crawl_time: ISO8601 格式时间戳(带时区)
6. 异常降级与容错 (Fault Tolerance)
6.1 降级链
- 主 API: https://weibo.com/ajax/side/hotSearch
- 主 API 失败(连续 ≥2 次)→ 切换到第三方聚合 API:
- 全部失败 → 返回缓存的上次成功结果(如存在);否则返回空数组并记录错误
6.2 异常处理规则
- 非 JSON 响应: 视为被拦截,触发 UA 轮换 + 延迟 5 秒后重试
- 状态码 403 / 429 / 418: 等待 30 秒后重试,最多重试 3 次
- 网络超时 / 连接错误: 指数退避 2 秒 → 5 秒 → 10 秒,然后切换下一级 API
- 所有异常必须记录到 stderr,不得抛出未处理堆栈导致进程崩溃
7. 合规风控 (Compliance)
- robots.txt: 遵守 weibo.com/robots.txt 的 Crawl-delay 精神,请求间隔 ≥10 秒(建议 ≥30 秒)
- 隐私保护: 禁止采集用户 UID、手机号、私信、完整用户画像等隐私数据;仅限公开榜单数据
- 数据保留期: 明确声明采集数据保留期 ≤90 天;超过 90 天的数据必须删除或仅保留聚合匿名化形式
- 负载控制: 避免高频请求对平台服务器造成过度压力
- 溯源: 必须在输出中保留 source_url,确保数据来源可追溯
8. 执行流程
- 初始化 Session 并配置 Headers(含 UA 轮换池)
- 尝试调用主 API 获取热搜数据
- 验证响应(JSON 格式 + ok=1,如适用)
- 主 API 失败时自动降级到第三方聚合 API
- 按清洗规则过滤和去重
- 逐条格式化为标准 schema
- 返回包含 count、data 的结果对象
- 可选:将结果保存为 UTF-8 JSON 文件(ensure_ascii=false)