hotspot/README.md

186 lines
7.0 KiB
Markdown
Raw Permalink 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. **设置预警** → 「预警规则」标签页配置自动通知
## 内置解析器
### 零配置即用9个
| 解析器名 | 平台 | 实时热度 | 需要认证 |
|---------|------|:---:|:---:|
| `weibo_hot` | 微博热搜 | ✅ | 无 — 公开接口 |
| `zhihu_hot` | 知乎热榜 | ✅ | 无 |
| `baidu_hot` | 百度热搜 | ✅ | 无 |
| `toutiao_hot` | 头条热榜 | ✅ | 无(需 Referer 头) |
| `bilibili_hot` | B站热门 | ✅ | 无 |
| `36kr_hot` | 36氪热榜 | ✅ | 无 |
| `github_trending` | GitHub Trending | ✅ | 无 — 匿名 60次/hToken 5000次/h |
| `hackernews` | HackerNews | ✅ | 无 |
| `v2ex_hot` | V2EX 热帖 | ✅ | 无 |
### 需要配置2个
| 解析器名 | 平台 | 需要什么 | 怎么获取 |
|---------|------|---------|---------|
| `rsshub` | RSSHub | RSSHub 实例地址 | 自建 `docker run rsshub/rsshub` 或用公共服务 |
| `douyin_hot` | 抖音热点 | ⚠️ 无官方 API | 第三方接口不稳定,建议用浏览器抓取 |
> 添加来源时只需选 `parser=builtin` + `builtin_name=weibo_hot` 即可,无需申请任何 Key。
## 提取器类型
| 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 | 自动解析,无需额外配置 |
## 抓取频率建议
| 解析器 | 推荐间隔 | 原因 |
|---------|:---:|------|
| `weibo_hot` | 5-10 分钟 | 热搜榜实时变动 |
| `zhihu_hot` | 10-15 分钟 | 热榜更新较快 |
| `baidu_hot` | 10-15 分钟 | 同知乎 |
| `toutiao_hot` | 15-20 分钟 | 新闻类更新稍慢 |
| `bilibili_hot` | 30 分钟 | 视频热度积累需时间 |
| `36kr_hot` | 30-60 分钟 | 一天几十条 |
| `github_trending` | 2-4 小时 | 限速 60次/h |
| `hackernews` | 15-30 分钟 | 首页排序变化频繁 |
| `v2ex_hot` | 15-30 分钟 | 社区帖子更新快 |
| `rsshub` | 取决于源 | RSS 源自身有间隔 |
默认 30 分钟是安全的——7 天半衰期模型下远远小于衰减窗口。
## 状态分类逻辑
```
热度衰减: 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`
- 抖音(`douyin_hot`)使用第三方聚合接口 `dy.feigua.cn`,非官方数据源,`builtin_name=douyin_hot` 仅作为参考
- 无 Headless Browser 集成(需单独部署 Playwright/Selenium
- GitHub 匿名访问限速 60次/小时,高频使用建议配 Personal Access Token 到 headers