skill.md
14.9 KB
Weibo Scraper Skill
Identity
- Name: weibo_scraper
- Version: 1.9.0
- Type: Scraping/Data Extraction
- Platform: Weibo (weibo.com)
Description
微博热点内容爬取技能。能够从微博平台爬取热搜榜、热门微博、热点话题等内容,提取结构化数据并进行清洗分类。强化版:详情页爬取 + 图片提取 + 简报生成。
Capabilities
- 热搜榜爬取 - 获取微博热搜榜单 Top 50
- 热门微博抓取 - 获取热门微博内容及作者信息
- 详情页爬取 - 访问热点新闻详情页,提取完整正文内容
- 图片提取 - 提取并保存微博配图,支持多源提取
- 简报生成 - 将图文内容整理为 HTML/Markdown 简报,支持降级处理
- 分类筛选 - 按娱乐、社会、科技、搞笑、体育、财经等分类
- 指标提取 - 提取点赞数、评论数、转发数、阅读数
- 数据清洗 - 去广告、去无效内容、格式标准化
- 定时爬取 - 支持 Cron 定时任务和增量更新
- 反爬合规 - UA轮换、频率控制、响应验证
Methodology
Step 1: 初始化请求环境
- 创建 requests Session
- 设置基础请求头 (User-Agent, Accept, Accept-Language, Referer)
- 配置超时 (10秒)
Step 2: 反爬合规控制
- User-Agent 轮换: 准备 10+ 个常用 UA,每次请求随机选择
- Chrome (Mac/Windows/Linux) 各版本
- Safari (iOS/Mac)
- Firefox (Windows/Linux)
- 移动端 UA (Android/iOS)
- 请求频率限制: 每次请求间隔 5-10 秒随机延迟
- 单 IP 限流: 每分钟请求数 ≤ 10
- 指数退避: 遇到 429/403 时,等待 60s 后重试,再失败则等待 120s
- Cookie 维护: 定期更新 Cookie,保持登录态
- 请求头完整性: 设置 Accept-Encoding, Accept-Language, Connection 等
Step 3: 执行爬取 (多 API 源)
- 主 API: 请求 PC 端热搜
https://weibo.com/ajax/side/hotSearch - 备用 API 1: 请求移动端热搜
https://m.weibo.cn/api/index/list?type=hot - 备用 API 2: 请求话题搜索
https://m.weibo.cn/api/container/getIndex - 优先使用返回 JSON 的 API,遇到 HTML 响应则切换
- 解析 JSON 响应
- 过滤低质量内容 (flag=1,2 为有效数据)
- 分类标注
Step 4: 数据验证与新鲜度
- 时间戳验证: 确保数据时间戳
- 新鲜度保障: 记录采集时间,过期数据标记
- JSON 验证: 检测返回是否为 HTML (验证码页面)
- 响应验证: 验证 JSON 解析是否成功,检查 ok 字段是否为 1
- 降级策略: 主 API 失败时自动切换备用 API
Step 5: 数据增强
- 字段补全: engagement.comments/shares 尝试从多源获取
- 作者信息补全: 尝试从话题页获取作者信息
- 多源验证: 对比多个数据源,确保数据准确性
- 数据清洗: 去广告、去无效内容、格式标准化
- 时间戳标准化: 将 API 返回的时间戳转为 ISO 格式
Step 6: 数据清洗与格式化
- 提取关键字段
- 转换中文数字 (如 "1.2万" → 12000)
- 标准化时间戳
- 生成最终 JSON,保留原始数据
Step 7: 详情页爬取 (强化版)
- 获取详情页 URL: 从热搜数据中提取
mid或构建搜索详情 URL - 搜索 API 获取详情: 使用
https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D{keyword}获取微博详情 - 解析正文内容: 从返回的 JSON 中提取
text字段(HTML 格式) - 提取纯文本: 使用 strip_tags 或正则去除 HTML 标签获取纯文本
内容截断处理: 如果内容过长,保留前 5000 字符
详情页反爬强化策略 ⭐:
- 专用 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,但继续生成简报
mid 提取: 从搜索结果 cards[].mblog.mid 获取微博 ID
多卡片处理: 搜索结果可能包含多个微博,取第一个有效 mblog
Step 8: 图片提取 (强化版)
- 提取 pic_ids: 从搜索 API 返回中获取
pic_ids数组 - 构建图片 URL: 使用
https://wx1.sinaimg.cn/large/{pic_id}.jpg格式 - 图片尺寸选择: 使用 large 尺寸减少水印干扰
- 下载图片: 如果需要保存图片,使用异步下载(并发 ≤ 3)
- 设置 Referer: 请求头设置 Referer 为 weibo.com 避免防盗链
- 图片有效性验证: 验证图片 URL 可访问
备用域名: 尝试 wx1/wx2/wx3/wx4.sinaimg.cn 多个域名提高成功率
多源提取强化 ⭐:
- 来源1: 从搜索 API 返回的
pic_ids数组提取 - 来源2: 从
media_urls字段提取(如果有) - 来源3: 从详情页 JSON 的
pics数组提取(详情页爬取成功时) - 降级处理: 如果所有图片源都失败,media_urls 设为空数组,并记录日志
- 来源1: 从搜索 API 返回的
多尺寸尝试: 某尺寸失败时尝试其他尺寸
- large → bmiddle → small → mw690
失败跳过: 单张图片下载失败不影响其他图片处理
Step 9: 简报生成 (强化版)
- 准备数据: 整合标题、正文、图片、热度、分类等信息
- 生成 Markdown 简报:
- 使用 markdown 模板渲染
- 包含:基本信息、核心内容、互动数据、关联图片、原始链接
- 格式化数字: 使用千位分隔符 (例如 1,234,567)
- 图片路径: 如果图片已下载,使用本地路径;否则使用 URL
- 生成 HTML 简报(可选):
- 使用 HTML 模板渲染
- 包含 CSS 样式、图片画廊、时间线
- 响应式设计: 支持移动端查看
- 图片灯箱: 点击可放大查看
输出文件: 保存为
brief_{timestamp}.md或brief_{timestamp}.html降级处理强化 ⭐:
- 内容缺失占位: 某字段缺失时,在简报中标注 [数据缺失]
- 标题缺失:
[标题获取失败] - 正文缺失:
[正文内容获取失败] - 图片缺失:
[无配图]
- 标题缺失:
- 部分成功处理: 即使只有部分数据,也生成简报(标注缺失部分)
- Fallback 机制:
- 如果详情页爬取失败,简报仍然生成基本信息部分
- 如果图片提取失败,简报不含图片但标注说明
- 如果全部失败,至少记录元数据和原始链接
- 内容缺失占位: 某字段缺失时,在简报中标注 [数据缺失]
简报字段:
- 基本信息: 发布时间、来源、热度排名、分类
- 核心内容: 标题 + 正文(纯文本,保留段落)
- 互动数据: 点赞、评论、转发、阅读(格式化)
- 关联图片: Markdown/HTML 图片标签(支持多图)
- 原始链接: 详情页 URL(可点击)
批量简报: 支持将多条热搜合并为一个综合简报
Step 10: 结果输出
- 保存到 workspace 目录
- 打印执行结果摘要
Implementation
API Endpoints
- 主 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 - 用户微博:
https://weibo.com/ajax/statuses/mymblog?uid={uid}- 需要登录 - 评论 API:
https://m.weibo.cn/comments/hotflow- 需要登录
Image URL Pattern
# 基础 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
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 详情页)
DETAIL_COOKIES = [
{"SUB": "xxx", "SUBP": "xxx"}, # 定期更新
{"SUB": "yyy", "SUBP": "yyy"},
{"SUB": "zzz", "SUBP": "zzz"},
]
Rate Limiting
- 请求间隔: 5-10 秒随机
- 每分钟请求数: ≤ 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
Brief Generation Templates
Markdown 模板
# 微博热点简报
## 基本信息
- 发布时间: {timestamp}
- 来源: {author_name} ({verified_status})
- 热度: 排名 {hot_rank} | 热度值 {hot_score}
- 状态: {status_indicator}
## 核心内容
{title}
{content_text}
## 互动数据
- 点赞: {likes:,}
- 评论: {comments:,}
- 转发: {shares:,}
- 阅读: {read_count:,}
## 关联图片
{images_markdown}
[无配图]
## 原始链接
{detail_url}
---
*来源: 微博热搜榜 | 采集时间: {crawl_time}*
HTML 模板
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>微博热点简报 {date}</title>
<style>
body { font-family: -apple-system, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.item { margin-bottom: 24px; border-bottom: 1px solid #eee; padding-bottom: 16px; }
.title { font-size: 18px; font-weight: bold; color: #333; }
.content { margin: 12px 0; color: #555; line-height: 1.6; }
.images { display: flex; gap: 8px; flex-wrap: wrap; }
.images img { max-width: 200px; border-radius: 4px; }
.meta { font-size: 12px; color: #999; }
.hot-rank { background: #ff3852; color: white; padding: 2px 8px; border-radius: 4px; }
.missing { color: #999; font-style: italic; }
</style>
</head>
<body>
<h1>微博热点简报 {date}</h1>
{items_html}
<p class="missing">[部分数据获取失败]</p>
</body>
</html>
Output Format
{
"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",
"反爬合规": {
"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
}
}
注意: engagement 和 author 字段中无法获取的数据使用
null而非0或-1,表示数据不可用而非数据缺失。必须通过多源验证尝试获取完整数据。
Execution Commands
# 爬取热搜榜
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/ # 输出目录
├── weibo_*.json # 爬取结果
└── brief_*.md # 生成的简报
Dependencies
- Python: 3.8+
- pip packages: requests
Quality Checks
- [x] 数据完整: engagement 数据字段存在,无法获取的标记为 null
- [x] 分类准确: category_tags 正确
- [x] 时效性: timestamp 为最近内容
- [x] 无效过滤: 已删除/广告内容已过滤
- [x] 反爬合规: UA 轮换、请求间隔、响应验证
- [x] 数据可用性: 保留 metadata 和 raw_data
- [x] 详情页爬取: 支持获取热点新闻详情页内容,强化反爬策略
- [x] 图片提取: 支持多源提取,有降级处理
- [x] 简报生成: 支持降级处理,标注缺失内容
训练记录
迭代历史
- 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池、图片多源提取、简报降级处理)
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.5+ (强化版 D6-D8)