# Weibo Scraper Skill
## Identity
- **Name**: weibo_scraper
- **Version**: 2.0.0
- **Type**: Scraping/Data Extraction
- **Platform**: Weibo (weibo.com)
## Description
微博热点内容爬取技能。能够从微博平台爬取热搜榜、热门微博、热点话题等内容,提取结构化数据并进行清洗分类。**强化版:多榜爬取 + 数据合并 + HTML/JSON 输出**。
## Capabilities
1. **多榜爬取** - 同时爬取 5 个榜单(我的热搜、热搜榜、文娱榜、生活榜、社会榜)
2. **热搜榜爬取** - 获取微博热搜榜单 Top 50
3. **热门微博抓取** - 获取热门微博内容及作者信息
4. **详情页爬取** - 访问热点新闻详情页,提取完整正文内容
5. **图片提取** - 提取并保存微博配图,支持多源提取
6. **简报生成** - 将图文内容整理为 HTML/Markdown 简报,支持降级处理
7. **分类筛选** - 按娱乐、社会、科技、搞笑、体育、财经等分类
8. **指标提取** - 提取点赞数、评论数、转发数、阅读数
9. **数据清洗** - 去广告、去无效内容、格式标准化
10. **定时爬取** - 支持 Cron 定时任务和增量更新
11. **反爬合规** - UA轮换、频率控制、响应验证
12. **数据合并存储** - 将多榜数据合并成一个数据库文件
13. **HTML 展现** - 生成 HTML 文档便于浏览
14. **JSON 存储** - 生成 JSON 文件用于数据存储
## Methodology
### Step 1: 初始化请求环境
1. 创建 requests Session
2. 设置基础请求头 (User-Agent, Accept, Accept-Language, Referer)
3. 配置超时 (10秒)
### Step 2: 反爬合规控制
1. **User-Agent 轮换**: 准备 10+ 个常用 UA,每次请求随机选择
- Chrome (Mac/Windows/Linux) 各版本
- Safari (iOS/Mac)
- Firefox (Windows/Linux)
- 移动端 UA (Android/iOS)
2. **请求频率限制**: 每次请求间隔 5-10 秒随机延迟
3. **单 IP 限流**: 每分钟请求数 ≤ 10
4. **指数退避**: 遇到 429/403 时,等待 60s 后重试,再失败则等待 120s
5. **Cookie 维护**: 定期更新 Cookie,保持登录态
6. **请求头完整性**: 设置 Accept-Encoding, Accept-Language, Connection 等
### Step 3: 多榜爬取 (核心新增)
1. **我的热搜**: `https://weibo.com/hot/mine` - 需要登录 Cookie
2. **热搜榜**: `https://weibo.com/hot/search` - 需要 Cookie
3. **文娱榜**: `https://weibo.com/hot/entertainment` - 需要 Cookie
4. **生活榜**: `https://weibo.com/hot/life` - 需要 Cookie
5. **社会榜**: `https://weibo.com/hot/social` - 需要 Cookie
**实现方式**:
- 每个榜单使用独立 API 调用
- 按顺序爬取,避免同时触发反爬
- 每个榜单间隔 10-15 秒
- 记录每个榜单的爬取状态和结果数
**备用移动端 API**:
- 移动端主 API: `https://m.weibo.cn/api/index/list?type=hot`
- 移动端娱乐: `https://m.weibo.cn/api/index/list?type=entertainment`
- 移动端生活: `https://m.weibo.cn/api/index/list?type=life`
- 移动端社会: `https://m.weibo.cn/api/index/list?type=social`
### Step 4: 数据验证与新鲜度
1. **时间戳验证**: 确保数据时间戳 < 1 小时
2. **新鲜度保障**: 记录采集时间,过期数据标记
3. **JSON 验证**: 检测返回是否为 HTML (验证码页面)
4. **响应验证**: 验证 JSON 解析是否成功,检查 ok 字段是否为 1
5. **降级策略**: 主 API 失败时自动切换备用 API
### Step 5: 数据合并与存储 (核心新增)
1. **合并策略**:
- 创建每日数据库文件 `weibo_daily_{date}.json`
- 包含所有榜单的 List 数据
- 每个热搜项包含 URL 地址
- 包含点击进入后的相关微博内容
2. **数据结构**:
```json
{
"date": "2026-03-29",
"crawl_time": "2026-03-29T12:00:00Z",
"boards": [
{
"name": "热搜榜",
"url": "https://weibo.com/hot/search",
"count": 50,
"items": [...]
},
{
"name": "文娱榜",
"url": "https://weibo.com/hot/entertainment",
"count": 50,
"items": [...]
}
],
"details": {
"hot_1": {
"content": "完整微博正文内容",
"author": "发布者用户名",
"views": 1234567,
"comments": 890,
"likes": 1234
}
}
}
```
3. **分目录存储** (如果数据量大):
- `daily/2026-03-29/` - 当日数据
- `details/` - 详情数据
- `images/` - 图片数据
- `briefs/` - 简报数据
### Step 6: 详情内容提取 (核心新增)
对每个热搜项,尝试提取:
1. **相关微博内容**: 访问详情页获取完整正文
2. **发布者信息**: 作者名称、粉丝数、认证状态
3. **观看量**: 阅读数/浏览量
4. **阅读量**: 读取数
5. **评论量**: 评论数
6. **热度**: 综合热度值
**API 调用**:
- 详情页 API: `https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D{keyword}`
- 备用 API: `https://m.weibo.cn/statuses/show?id={mid}`
### Step 7: 数据清洗与格式化
1. 提取关键字段
2. 转换中文数字 (如 "1.2万" → 12000)
3. 标准化时间戳
4. 生成最终 JSON,保留原始数据
### Step 8: 详情页爬取 (强化版)
1. **获取详情页 URL**: 从热搜数据中提取 `mid` 或构建搜索详情 URL
2. **搜索 API 获取详情**: 使用 `https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D{keyword}` 获取微博详情
3. **解析正文内容**: 从返回的 JSON 中提取 `text` 字段(HTML 格式)
4. **提取纯文本**: 使用 strip_tags 或正则去除 HTML 标签获取纯文本
5. **内容截断处理**: 如果内容过长,保留前 5000 字符
6. **详情页反爬强化策略** ⭐:
- **专用 Cookie 池**: 维护 3-5 个有效 Cookie,定期刷新,与主 API 分离
- **代理 IP 支持**: 支持 HTTP/HTTPS 代理,遇到 403/429 自动切换
- **请求间隔**: 8-15 秒随机(比普通请求更长)
- **失败重试机制**:
- 首次失败: 等待 60s 重试
- 二次失败: 更换 UA/Cookie,等待 120s 重试
- 三次失败: 切换代理 IP,等待 240s 重试
- 仍然失败: 标记失败,记录日志,继续处理下一条
- **备用 API**: 详情页失败时尝试:
- `https://m.weibo.cn/statuses/show?id={mid}`
- `https://m.weibo.cn/detail/{mid}`
- **降级处理**: 详情页失败时,记录 metadata.详情页爬取成功=false,但继续生成简报
7. **mid 提取**: 从搜索结果 cards[].mblog.mid 获取微博 ID
8. **多卡片处理**: 搜索结果可能包含多个微博,取第一个有效 mblog
### Step 9: 图片提取 (强化版)
1. **提取 pic_ids**: 从搜索 API 返回中获取 `pic_ids` 数组
2. **构建图片 URL**: 使用 `https://wx1.sinaimg.cn/large/{pic_id}.jpg` 格式
3. **图片尺寸选择**: 使用 large 尺寸减少水印干扰
4. **下载图片**: 如果需要保存图片,使用异步下载(并发 ≤ 3)
5. **设置 Referer**: 请求头设置 Referer 为 weibo.com 避免防盗链
6. **图片有效性验证**: 验证图片 URL 可访问
7. **备用域名**: 尝试 wx1/wx2/wx3/wx4.sinaimg.cn 多个域名提高成功率
8. **多源提取强化** ⭐:
- **来源1**: 从搜索 API 返回的 `pic_ids` 数组提取
- **来源2**: 从 `media_urls` 字段提取(如果有)
- **来源3**: 从详情页 JSON 的 `pics` 数组提取(详情页爬取成功时)
- **降级处理**: 如果所有图片源都失败,media_urls 设为空数组,并记录日志
9. **多尺寸尝试**: 某尺寸失败时尝试其他尺寸
- large → bmiddle → small → mw690
10. **失败跳过**: 单张图片下载失败不影响其他图片处理
### Step 10: 结果展现与输出 (核心新增)
1. **更新每日总 List**: 保存到 `daily/weibo_daily_{date}.json`
2. **生成 HTML 文档**: 便于浏览
- 使用 HTML 模板渲染
- 包含 CSS 样式、图片画廊、时间线
- 响应式设计
- 支持点击展开详情
3. **生成 JSON 文件**: 用于数据存储
- 完整数据结构
- 包含所有榜单和详情
4. **分目录存储** (可选):
- `daily/` - 每日汇总
- `details/` - 详情数据
- `images/` - 图片
- `briefs/` - 简报
**HTML 模板结构**:
```html
微博热搜日报 {date}
微博热搜日报 {date}
{boards_html}
```
## Implementation
### API Endpoints
- **我的热搜 (PC)**: `https://weibo.com/hot/mine` - 需要 Cookie
- **热搜榜 (PC)**: `https://weibo.com/hot/search` - 需要 Cookie
- **文娱榜 (PC)**: `https://weibo.com/hot/entertainment` - 需要 Cookie
- **生活榜 (PC)**: `https://weibo.com/hot/life` - 需要 Cookie
- **社会榜 (PC)**: `https://weibo.com/hot/social` - 需要 Cookie
- **主 API (PC 端)**: `https://weibo.com/ajax/side/hotSearch` - 需要 Cookie
- **备用 API 1 (移动端)**: `https://m.weibo.cn/api/index/list?type=hot` - 无需 Cookie
- **备用 API 2 (话题)**: `https://m.weibo.cn/api/container/getIndex` - 无需 Cookie
- **详情页 API**: `https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D{keyword}` - 无需 Cookie
- 详情页备用 API: `https://m.weibo.cn/statuses/show?id={mid}` - 无需 Cookie
### Image URL Pattern
```python
# 基础 URL
BASE_IMAGE_URL = "https://wx1.sinaimg.cn/"
# 尺寸选项
SIZE_SMALL = "small" # 缩略图
SIZE_MIDDLE = "bmiddle" # 中图
SIZE_LARGE = "large" # 大图
SIZE_ORIGINAL = "mw690" # 原图
# 完整 URL 格式
image_url = f"https://wx1.sinaimg.cn/{SIZE}/{pic_id}.jpg"
# 多域名备用
DOMAINS = ["wx1.sinaimg.cn", "wx2.sinaimg.cn", "wx3.sinaimg.cn", "wx4.sinaimg.cn"]
```
### User-Agent Pool
```python
USER_AGENTS = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 Chrome/112.0.0.0 Mobile Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Version/17.0 Safari/605.1.15"
]
```
### Cookie Pool (for 详情页)
```python
DETAIL_COOKIES = [
{"SUB": "xxx", "SUBP": "xxx"}, # 定期更新
{"SUB": "yyy", "SUBP": "yyy"},
{"SUB": "zzz", "SUBP": "zzz"},
]
```
### Rate Limiting
- 请求间隔: 5-10 秒随机
- 多榜爬取间隔: 10-15 秒
- 每分钟请求数: ≤ 10
- 超时重试: 3 次
- 退避策略: 遇到 403/429 等待 60s/120s 后重试
- **详情页请求间隔**: 8-15 秒(详情页更敏感)
### Error Handling & Fallback Strategy
- **多榜爬取失败**: 跳过失败榜单,继续其他榜单
- **主 API 失败**: 自动切换到移动端 API
- **详情页失败**: 记录日志,标记失败,继续处理下一条,不阻塞流程
- **图片提取失败**: 尝试备用来源,全部失败则设为空数组
- **简报生成失败**: 使用降级模板,标注缺失内容
- 403 Forbidden: 更换 User-Agent 或切换备用 API
- 429 Too Many Requests: 指数退避 (60s, 120s, 240s) 后重试
- 网络超时: 重试,超时递增
- 反爬机制: 降低频率或切换 API
- HTML 响应: 检测到验证码页面,更换 UA 并尝试备用 API
### Output Format
```json
{
"source": {
"platform": "weibo",
"category": "娱乐",
"hot_id": "xxx",
"url": "https://weibo.com/xxx"
},
"engagement": {
"likes": 12345,
"comments": null,
"shares": null,
"read_count": 123456
},
"content": {
"title": "热搜标题",
"text": "微博正文内容",
"media_urls": ["https://xxx.jpg"],
"category_tags": ["娱乐", "明星", "综艺"]
},
"author": {
"username": null,
"followers": null,
"verified": false
},
"timestamp": "2024-01-01T00:00:00Z",
"metrics": {
"hot_rank": 1,
"hot_score": 999999,
"trend": "up"
},
"metadata": {
"采集时间": "2024-01-01T00:00:00Z",
"数据来源": "weibo_hotsearch_api",
"API版本": "v2",
"多榜爬取": {
"enabled": true,
"boards": ["热搜榜", "文娱榜", "生活榜", "社会榜"],
"成功": true
},
"反爬合规": {
"ua_rotation": true,
"rate_limiting": true,
"response_validation": true
},
"详情页爬取": {
"enabled": true,
"成功": true,
"正文提取": true,
"图片提取": true,
"失败原因": null
}
},
"raw_data": {},
"brief": {
"generated": true,
"format": "markdown",
"path": "workspace/brief_20260328.md",
"降级处理": false
}
}
```
### 每日汇总数据结构 (新增)
```json
{
"date": "2026-03-29",
"crawl_time": "2026-03-29T12:00:00Z",
"boards": [
{
"name": "热搜榜",
"url": "https://weibo.com/hot/search",
"count": 50,
"items": [
{
"rank": 1,
"title": "热搜标题",
"url": "https://weibo.com/xxx",
"hot_score": 999999,
"detail_url": "https://m.weibo.cn/detail/xxx"
}
]
},
{
"name": "文娱榜",
"url": "https://weibo.com/hot/entertainment",
"count": 50,
"items": [...]
},
{
"name": "生活榜",
"url": "https://weibo.com/hot/life",
"count": 50,
"items": [...]
},
{
"name": "社会榜",
"url": "https://weibo.com/hot/social",
"count": 50,
"items": [...]
}
],
"details": {
"hot_1": {
"content": "完整微博正文内容...",
"author": "发布者用户名",
"author_followers": 100000,
"author_verified": true,
"views": 1234567,
"read_count": 1234567,
"comments_count": 890,
"likes_count": 1234,
"shares_count": 567,
"hot": 999999
}
},
"output_files": {
"json": "daily/weibo_daily_20260329.json",
"html": "daily/weibo_daily_20260329.html"
}
}
```
> **注意**: engagement 和 author 字段中无法获取的数据使用 `null` 而非 `0` 或 `-1`,表示数据不可用而非数据缺失。**必须通过多源验证尝试获取完整数据**。
## Execution Commands
```bash
# 多榜爬取 + 数据合并
python3 weibo_scraper.py --boards all --merge --output daily
# 多榜爬取 + 详情页 + 简报
python3 weibo_scraper.py --boards all --detail --brief --limit 10
# 爬取热搜榜
python3 weibo_scraper.py --category 娱乐 --limit 20
# 爬取热门微博
python3 weibo_scraper.py --type hot --limit 50
# 详情页爬取 + 简报生成
python3 weibo_scraper.py --detail --brief --limit 10
# 定时增量更新
python3 weibo_scraper.py --cron --output /path/to/output.json
```
## File Structure
```
weibo-scraper/
├── .claude/
│ └── skills/
│ └── main_skill/
│ └── SKILL.md (本文件)
├── weibo_scraper.py # 主脚本
├── requirements.txt # Python 依赖
└── workspace/ # 输出目录
├── daily/ # 每日汇总数据
│ ├── weibo_daily_20260329.json
│ └── weibo_daily_20260329.html
├── details/ # 详情数据
├── images/ # 图片数据
├── briefs/ # 简报数据
├── weibo_*.json # 爬取结果
└── brief_*.md # 生成的简报
```
## Dependencies
- Python: 3.8+
- pip packages: requests
## Quality Checks
- [x] 多榜爬取: 支持 5 个榜单同时爬取
- [x] 数据合并: 合并为每日数据库文件
- [x] 数据完整: engagement 数据字段存在,无法获取的标记为 null
- [x] 分类准确: category_tags 正确
- [x] 时效性: timestamp 为最近内容
- [x] 无效过滤: 已删除/广告内容已过滤
- [x] 反爬合规: UA 轮换、请求间隔、响应验证
- [x] 数据可用性: 保留 metadata 和 raw_data
- [x] 详情页爬取: 支持获取热点新闻详情页内容,强化反爬策略
- [x] 图片提取: 支持多源提取,有降级处理
- [x] 简报生成: 支持降级处理,标注缺失内容
- [x] HTML 展现: 生成 HTML 文档便于浏览
- [x] JSON 存储: 生成 JSON 文件用于数据存储
---
## 训练记录
### 迭代历史
- v1.0.0 → v1.1.0: 增加 UA 轮换、频率控制
- v1.1.0 → v1.2.0: 将 -1 改为 null,增加响应验证
- v1.2.0 → v1.3.0: 增加 metadata 和 raw_data 字段
- v1.3.0 → v1.4.0: 增加多 API 源支持、新鲜度验证、降级策略
- v1.4.0 → v1.5.0: 增加数据增强步骤、多源验证
- v1.5.0 → v1.6.0: 优化完整流程、强化多源验证
- v1.6.0 → v1.7.0: 增加详情页爬取、图片提取、简报生成能力
- v1.7.0 → v1.8.0: 增加详细反爬策略、简报模板
- v1.8.0 → v1.9.0: 强化 D6-D8 (详情页Cookie池、图片多源提取、简报降级处理)
- v1.9.0 → v2.0.0: 增加多榜爬取(5个榜单)、数据合并存储、HTML/JSON 输出
### Benchmark 得分
- v1.3.0: 92.65
- v1.4.0: 88.25 (评估)
- v1.5.0: 89.80 (评估)
- v1.6.0: 93.50
- v1.7.0: 88.65 (预估)
- v1.9.0: 91.34
- v2.0.0: 目标 90+ (多榜爬取 + 数据合并)
---
## 新增功能说明 (v2.0.0)
### 多榜爬取
- 支持 5 个榜单同时爬取
- 每个榜单独立 API 调用
- 间隔爬取避免反爬
### 数据合并
- 每日数据合并为一个 JSON 文件
- 包含所有榜单 List 和详情数据
- 支持分目录存储大数据量
### HTML/JSON 输出
- 生成 HTML 文档便于浏览
- 生成 JSON 文件用于存储
- 支持响应式设计和交互