hotspot/README.md
yumoqing b9bd705b43 fix: address dev standards — README, SKILL.md, logging, docs
- Rewrite README: full install steps, usage flow, parser_config examples,
  builtin table, extractor types, status logic, known limitations
- Add SKILL.md: architecture, adding parsers, deployment checklist, pitfalls
- engine.py: replace bare except with traceback logging
- parsers.py: CSS extractor docstring documents lightweight limitation
2026-08-01 15:38:20 +08:00

159 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 热点雷达 (Hotspot Radar)
Sage 框架模块 — 指定来源的热点聚合分析平台,支持动态添加来源。
## 功能
- **11 个内置平台解析器**:微博/知乎/百度/头条/B站/抖音/36氪/GitHub/HackerNews/V2EX/RSSHub
- **4 种可配置提取器**json_path / css(轻量) / regex / rss
- **每条来源自带 parser_config**JSON 格式的提取规则,同类型不同来源可用不同规则
- **五维分析**:时效 / 热度 / 内容 / 传播 / 受众,每维度 0-100 分
- **自动状态分类**7 天半衰期指数衰减模型emerging → rising → hot → cooling → expired
- **抓取日志**:每次执行一条审计记录(耗时/成功数/错误/HTTP状态码
- **预警规则**:热度阈值 / 速度阈值 / 情感变化触发
## 目录结构
```
hotspot/
├── hotspot/ # Python 包
│ ├── __init__.py # public API: run_fetch, run_analysis, get_stats
│ ├── engine.py # 抓取引擎 — 调度→fetch→extract→save→log
│ ├── analysis.py # 五维分析 + 衰减模型状态分类
│ ├── parsers.py # 11 内置解析器 + 4 通用提取器
│ └── db.py # 数据库操作 (CRUD helpers)
├── json/ # Sage 表定义 (6 张表)
├── wwwroot/hotspot/ # Sage Web 层
│ ├── index.ui # 仪表盘 UI (7 统计卡片 + 6 标签页)
│ ├── fetch_now.dspy # 触发抓取 (薄封装)
│ ├── analyze.dspy # 触发分析 (薄封装)
│ └── stats.dspy # 统计查询 (薄封装)
├── ddl/mysql.sql # 建表 SQL (6 张表 + 索引)
└── install/ # 部署片段
├── load_path_append.txt # 追加到 load_path.py 的路径
└── menu_append.json # 追加到 menu.ui 的菜单项
```
## 安装
### 1. 复制文件到 Sage 部署目录
```bash
SAGE_ROOT=/path/to/sage
git clone git@git.opencomputing.cn:yumoqing/hotspot.git /tmp/hotspot
# Python 包
cp -r /tmp/hotspot/hotspot $SAGE_ROOT/
# 表定义
cp /tmp/hotspot/json/hotspot_*.json $SAGE_ROOT/json/
# Web UI + 端点
cp -r /tmp/hotspot/wwwroot/hotspot $SAGE_ROOT/wwwroot/
```
### 2. 建表
```bash
mysql -u <user> -p sage < /tmp/hotspot/ddl/mysql.sql
```
### 3. 注册权限
打开 `$SAGE_ROOT/load_path.py`,找到末尾的 `"""` 结束符,在它**前面**插入 `install/load_path_append.txt` 的内容。
```bash
cd /tmp/hotspot
# 找到 SAGE_ROOT/load_path.py 中最后一个 """ 的前一行
# 把 install/load_path_append.txt 的内容粘贴进去
# 然后:
cd $SAGE_ROOT && python load_path.py
```
### 4. 添加菜单
打开 `$SAGE_ROOT/wwwroot/menu.ui`,在 `items` 数组末尾追加 `install/menu_append.json` 的内容(注意前面加逗号)。
### 5. 重启 Sage
访问 `/hotspot`
## 使用流程
1. **添加来源** → 进入「来源管理」标签页,点击新增
- 类型选 `api` 配合 `parser=builtin` 使用内置解析器
- 或选 `rss`/`api` 配合 `parser=json_path` 自定义提取规则
2. **配置提取规则** → 在 `parser_config` 字段填入 JSON
```json
{"parser": "builtin", "builtin_name": "weibo_hot"}
```
或自定义:
```json
{
"parser": "json_path",
"item_path": "$.data.list[*]",
"field_map": {
"title": "word",
"url": "link",
"heat_score": "hotValue"
}
}
```
3. **配置调度** → 在「调度配置」标签页添加 cron 或间隔
4. **执行抓取** → 仪表盘点击「立即抓取全部来源」
5. **查看日志** → 「抓取日志」标签页检查成功率/错误详情
6. **执行分析** → 点击「执行分析」计算五维评分和状态
7. **浏览热点** → 「热点条目」标签页按状态筛选
8. **设置预警** → 「预警规则」标签页配置自动通知
## 内置解析器
| 解析器名 | 平台 | API 端点 | 备注 |
|---------|------|---------|------|
| `weibo_hot` | 微博热搜 | weibo.com/ajax/side/hotSearch | 需 UA 头 |
| `zhihu_hot` | 知乎热榜 | zhihu.com/api/v3/feed/topstory/hot-lists | — |
| `baidu_hot` | 百度热搜 | top.baidu.com/board | — |
| `toutiao_hot` | 头条热榜 | toutiao.com/hot-event/hot-board | 需 Referer |
| `bilibili_hot` | B站热门 | api.bilibili.com/x/web-interface/popular | — |
| `douyin_hot` | 抖音热点 | 第三方聚合接口 | 非官方,可能不稳定 |
| `36kr_hot` | 36氪热榜 | 36kr.com/api/search/list/info-flow/hot | — |
| `github_trending` | GitHub | api.github.com/search/repositories | — |
| `hackernews` | HackerNews | firebaseio.com (两步抓取) | — |
| `v2ex_hot` | V2EX | v2ex.com/api/topics/hot.json | — |
| `rsshub` | RSSHub | 来源 url 即 RSSHub 地址 | 解析 RSS/Atom |
## 提取器类型
| parser 值 | 适用场景 | 配置要点 |
|-----------|---------|---------|
| `builtin` | 使用内置解析器 | 设置 `builtin_name` |
| `json_path` | REST API 返回 JSON | `item_path` + `field_map` |
| `css` | HTML 页面 (轻量) | `item_selector` + `field_map` — 仅支持 `<a>` 标签提取,完整 CSS 需引入 BeautifulSoup |
| `regex` | 非结构化文本 | `item_regex` (命名捕获组) + `field_map` |
| `rss` | RSS/Atom feed | 自动解析,无需额外配置 |
## 状态分类逻辑
```
热度衰减: adjusted_heat = raw_heat × e^(-hours_alive / 168)
状态判定:
hours_alive > 336 (14天) → expired
336 > hours_alive > 168 → cooling
adjusted_heat > 5000 → hot
adjusted_heat > 500 → rising (velocity > 50) / emerging
adjusted_heat > 100 → rising (velocity > 100) / emerging
其他 → emerging
```
## 依赖
- **Sage** >= 0.0.1
- **aiohttp** (Python, 用于异步 HTTP 请求)
- **MySQL** / MariaDB
## 已知限制
- CSS 提取器为轻量正则实现,复杂页面结构建议使用 `json_path` 或 `builtin`
- 抖音解析器使用第三方聚合接口,官方 API 需企业资质
- 无 Headless Browser 集成(需单独部署 Playwright/Selenium