# Weibo Scraper Skill ## Identity - **Name**: weibo_scraper - **Version**: 1.9.0 - **Type**: Scraping/Data Extraction - **Platform**: Weibo (weibo.com) ## Description 微博热点内容爬取技能。能够从微博平台爬取热搜榜、热门微博、热点话题等内容,提取结构化数据并进行清洗分类。**强化版:详情页爬取 + 图片提取 + 简报生成**。 ## Capabilities 1. **热搜榜爬取** - 获取微博热搜榜单 Top 50 2. **热门微博抓取** - 获取热门微博内容及作者信息 3. **详情页爬取** - 访问热点新闻详情页,提取完整正文内容 4. **图片提取** - 提取并保存微博配图,支持多源提取 5. **简报生成** - 将图文内容整理为 HTML/Markdown 简报,支持降级处理 6. **分类筛选** - 按娱乐、社会、科技、搞笑、体育、财经等分类 7. **指标提取** - 提取点赞数、评论数、转发数、阅读数 8. **数据清洗** - 去广告、去无效内容、格式标准化 9. **定时爬取** - 支持 Cron 定时任务和增量更新 10. **反爬合规** - UA轮换、频率控制、响应验证 ## 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: 执行爬取 (多 API 源) 1. **主 API**: 请求 PC 端热搜 `https://weibo.com/ajax/side/hotSearch` 2. **备用 API 1**: 请求移动端热搜 `https://m.weibo.cn/api/index/list?type=hot` 3. **备用 API 2**: 请求话题搜索 `https://m.weibo.cn/api/container/getIndex` 4. 优先使用返回 JSON 的 API,遇到 HTML 响应则切换 5. 解析 JSON 响应 6. 过滤低质量内容 (flag=1,2 为有效数据) 7. 分类标注 ### Step 4: 数据验证与新鲜度 1. **时间戳验证**: 确保数据时间戳 < 1 小时 2. **新鲜度保障**: 记录采集时间,过期数据标记 3. **JSON 验证**: 检测返回是否为 HTML (验证码页面) 4. **响应验证**: 验证 JSON 解析是否成功,检查 ok 字段是否为 1 5. **降级策略**: 主 API 失败时自动切换备用 API ### Step 5: 数据增强 1. **字段补全**: engagement.comments/shares 尝试从多源获取 2. **作者信息补全**: 尝试从话题页获取作者信息 3. **多源验证**: 对比多个数据源,确保数据准确性 4. **数据清洗**: 去广告、去无效内容、格式标准化 5. **时间戳标准化**: 将 API 返回的时间戳转为 ISO 格式 ### Step 6: 数据清洗与格式化 1. 提取关键字段 2. 转换中文数字 (如 "1.2万" → 12000) 3. 标准化时间戳 4. 生成最终 JSON,保留原始数据 ### Step 7: 详情页爬取 (强化版) 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 8: 图片提取 (强化版) 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 9: 简报生成 (强化版) 1. **准备数据**: 整合标题、正文、图片、热度、分类等信息 2. **生成 Markdown 简报**: - 使用 markdown 模板渲染 - 包含:基本信息、核心内容、互动数据、关联图片、原始链接 - **格式化数字**: 使用千位分隔符 (例如 1,234,567) - **图片路径**: 如果图片已下载,使用本地路径;否则使用 URL 3. **生成 HTML 简报**(可选): - 使用 HTML 模板渲染 - 包含 CSS 样式、图片画廊、时间线 - **响应式设计**: 支持移动端查看 - **图片灯箱**: 点击可放大查看 4. **输出文件**: 保存为 `brief_{timestamp}.md` 或 `brief_{timestamp}.html` 5. **降级处理强化** ⭐: - **内容缺失占位**: 某字段缺失时,在简报中标注 [数据缺失] - 标题缺失: `[标题获取失败]` - 正文缺失: `[正文内容获取失败]` - 图片缺失: `[无配图]` - **部分成功处理**: 即使只有部分数据,也生成简报(标注缺失部分) - **Fallback 机制**: - 如果详情页爬取失败,简报仍然生成基本信息部分 - 如果图片提取失败,简报不含图片但标注说明 - 如果全部失败,至少记录元数据和原始链接 6. **简报字段**: - 基本信息: 发布时间、来源、热度排名、分类 - 核心内容: 标题 + 正文(纯文本,保留段落) - 互动数据: 点赞、评论、转发、阅读(格式化) - 关联图片: Markdown/HTML 图片标签(支持多图) - 原始链接: 详情页 URL(可点击) 7. **批量简报**: 支持将多条热搜合并为一个综合简报 ### Step 10: 结果输出 1. 保存到 workspace 目录 2. 打印执行结果摘要 ## 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 ```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 - 超时重试: 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 模板 ```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 模板 ```html 微博热点简报 {date}

微博热点简报 {date}

{items_html}

[部分数据获取失败]

``` ## 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", "反爬合规": { "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 ```bash # 爬取热搜榜 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)