微博热搜监控与推送服务 — 定时抓取微博热搜榜,根据自定义订阅规则匹配后,通过飞书/钉钉/企微/Telegram 等渠道推送通知。
- 定时抓取 微博热搜榜,按整分钟刻度执行并保存历史快照
- 自动清理 可配置数据保留天数,过期的热搜快照与推送日志自动删除,避免数据库无限增长
- 灵活订阅 支持关键词(含正则/前缀匹配)、排除词、标签过滤(爆/热/新)、最低热度阈值
- 多渠道推送 飞书卡片消息、钉钉、企业微信、微信 Gateway Webhook、Telegram、通用 Webhook
- 批量推送 一次匹配多条热搜合并为一条消息
- 智能去重 可配置的去重窗口,避免重复推送
- 趋势查询 关键词排名历史趋势
- Web 管理界面 管理订阅、通道、查看推送日志
| 实时热搜与数据概览 | 24 小时热度趋势 |
|---|---|
![]() |
![]() |
| 订阅规则配置 | 多渠道推送配置 |
![]() |
![]() |
| 层 | 技术 |
|---|---|
| 框架 | Spring Boot 3.5 + Java 21 |
| 数据库 | SQLite + Hibernate (JPA) |
| 安全 | Spring Security + JWT (jjwt 0.12) + BCrypt |
| 前端 | 原生 HTML/CSS/JS + Chart.js v4 |
| 文档 | springdoc-openapi (Swagger UI) |
| 部署 | Docker + docker-compose |
# 1. 复制环境变量模板为 .env(Windows 用 Copy-Item .env.example .env)
cp .env.example .env
# 2. 编辑 .env,填入 JWT_SECRET(必填,留空启动会直接报错;任意长度均可,建议 32+ 字符随机串)
# 生成示例:openssl rand -base64 48
# PowerShell:[Convert]::ToBase64String((1..48 | ForEach-Object { Get-Random -Maximum 256 }))
# 3. 构建并启动
docker compose up -d --build
# 4. 访问(docker-compose 默认映射到 127.0.0.1:28080)
# 管理界面: http://localhost:28080
# 默认账号: admin / admin123(可在 .env 中用 ADMIN_INITIAL_PASSWORD 覆盖;首次登录强制修改密码)容器以非 root 用户(uid=100, gid=101)运行。Linux 宿主机首次启动前请执行
mkdir -p data && sudo chown -R 100:101 data,否则 SQLite 数据目录不可写。
# 需要 Java 21+ 和 Maven 3.9+
export JWT_SECRET=your-secret-key-at-least-32-chars
mvn spring-boot:runDocker 部署时通过项目根目录的 .env 文件传入(从 .env.example 复制并修改,该文件不会被提交);本地开发时也可直接用 shell 环境变量。
| 变量 | 默认值 | 说明 |
|---|---|---|
JWT_SECRET |
无(必填) | JWT 签名密钥,任意长度(内部经 SHA-256 派生);建议 32+ 字符随机串 |
ADMIN_INITIAL_PASSWORD |
无 | 首次启动创建 admin 账号时的初始密码;未设置时使用内置默认值并强制首登改密 |
SPRING_JPA_HIBERNATE_DDL_AUTO |
update |
数据库 schema 策略 |
编辑 application.yml:
app:
schedule:
interval-minutes: 10 # 默认抓取频率,可在系统配置页面动态修改
zone: Asia/Shanghai # 调度时区;10 分钟对应 :00、:10、:20 等刻度
snapshot:
retention-days: 30 # 数据保留天数(快照与推送日志),可在系统配置页面动态修改
cleanup-cron: "0 30 3 * * *" # 每天 03:30 清理,应用启动时也会清理一次
dedupe:
window-hours: 6 # 去重窗口(小时内同一关键词不重复推送)
push:
retry:
max-attempts: 3 # 上游限频时的退避重试次数
delay-seconds: 12 # 每次重试间隔(秒)
fetcher:
user-agent: "..." # 抓取请求的 UA
# cookie: "SUB=xxx" # 可选,微博 Cookie 避免 403每条订阅支持以下过滤条件(所有条件 AND 逻辑):
| 条件 | 说明 | 示例 |
|---|---|---|
| 关键词 | 空 = 匹配全部;支持 prefix:XXX、regex:PATTERN |
周杰伦, prefix:春晚, regex:.*演唱会 |
| 排除词 | 排除包含指定文本的热搜 | 广告 |
| 标签 | 仅匹配指定标签(爆/热/新等) | 爆, 热 |
| 最低热度 | 低于此值不推送 | 500000 |
| 生效时间 | 可选的开始和结束时间,页面按北京时间(UTC+8)精确到秒;留空表示长期 | 2026-07-21 10:00:00 |
广告类热搜自动排除。未到开始时间或已经到达结束时间的规则不会触发推送;已过期规则可在“历史规则”中查看。
| 通道 | 配置字段 |
|---|---|
| 飞书 Webhook | mode=webhook + webhookUrl — 飞书群自定义机器人 Webhook 地址 |
| 飞书自建应用 | mode=app + appId + appSecret + receiveId + receiveIdType — 通过飞书应用机器人发送消息 |
| 钉钉 | webhookUrl — 钉钉机器人 Webhook 地址 |
| 企业微信 | webhookUrl — 企微机器人 Webhook 地址 |
| 微信机器人 | apiBaseUrl + token + chat;可选 shortLinkEnabled |
| 微信 Gateway Webhook | webhookUrl + token + wxIdList;可选 tokenHeader(默认 X-Webhook-Token) |
| Telegram | token + chatId — Bot Token 和 Chat ID |
| 通用 Webhook | webhookUrl — 任意 HTTP POST 端点 |
推荐将 Sink 作为独立服务部署到 Cloudflare Workers,而不是把其源码集成进本项目。这样 Sink 的 KV、分析能力和发布周期与热搜服务解耦,本项目只通过服务端调用 POST /api/link/create。
- 按 Sink 文档部署 Workers、绑定自定义域名,并配置
NUXT_SITE_TOKEN。 - 在“系统配置 → Sink 短链服务”填写
Sink Base URL(例如https://s.example.com)和与NUXT_SITE_TOKEN相同的Sink Site Token。 - 编辑任意推送通道,勾选“使用 Sink 短链接”。飞书、钉钉、企业微信、微信机器人、微信 Gateway Webhook、Telegram 和通用 Webhook 均支持。
仅当通道开关启用且全局 Sink 配置完整时才会缩短微博 URL。Sink 不可用或返回异常时,本次推送自动保留原始长链接,消息不会因短链服务故障而中断。旧版保存在微信通道中的 Sink 凭据会在启动时自动迁移到全局配置。
详细产品规划见 product-plan.md。当前产品化方向是:以“微博热搜订阅提醒”为核心能力,后续承载在微信工具聚合小程序中;主服务负责抓取、匹配、去重和通知策略,微信云函数只作为发送小程序订阅消息的轻量钩子。
- 微信小程序登录:通过
wx.login和主服务code2session建立openid -> userId。 - 用户私有数据:订阅规则、通道配置、命中事件、通知日志按
userId收口;热搜快照作为全局共享数据。 - 热搜订阅创建:支持关键词、标签过滤、最低热度和排除词。
- 命中事件聚合:新增
match_events,按userId + subscriptionId + keyword + activeWindow聚合,避免抓取频率越高命中次数越失真。 - 微信订阅消息:小程序端申请授权,主服务记录可发送额度,云函数负责调用微信订阅消息 API。
- 安全云函数钩子:主服务调用云函数时增加 shared secret、timestamp、nonce、signature 和防重放校验。
- 通知降噪:默认只在首次命中、标签升级、进入高排名或热度越过阈值时通知。
- 订阅规则预览:创建规则时即时展示当前热搜可命中内容。
- 命中记录列表:展示今日新增、观察中、已通知、未通知原因。
- 通道管理增强:完善小程序订阅消息、飞书 Webhook、飞书自建应用、企微、钉钉、Telegram、通用 Webhook 的配置与测试体验。
- 抓取状态页:展示最近抓取时间、抓取条数、失败原因和下一次抓取时间。
- 简单工具广场:先放热搜提醒、天气、计算器、汇率、第三方小程序跳转等轻量入口。
- 完整工具生态与大量第三方小程序跳转。
- 团队/租户体系、复杂权限和操作审计。
- 报表中心、日报周报和高级趋势分析。
- 计费系统、AI 舆情分析、多平台 App。
启动后访问 http://localhost:8080/swagger-ui.html 查看完整 API 文档。
主要端点:
GET /api/hotsearch 最新热搜数据
POST /api/hotsearch/trigger 手动触发推送管线(异步执行,立即返回)
GET /api/hotsearch/trend 关键词排名趋势
GET /api/hotsearch/history 历史快照列表
GET /api/subscriptions 我的订阅列表
GET /api/subscriptions/history 已过期订阅列表
POST /api/subscriptions 创建订阅
PUT /api/subscriptions/{id} 更新订阅
DELETE /api/subscriptions/{id} 删除订阅
GET /api/channels 我的推送通道
POST /api/channels 创建通道
PUT /api/channels/{id} 更新通道
DELETE /api/channels/{id} 删除通道
POST /api/channels/{id}/test 发送测试消息
GET /api/delivery-logs 推送日志(按批次)
GET /api/config 系统配置
PUT /api/config 更新配置
POST /api/auth/login 登录
POST /api/auth/change-password 修改密码
src/main/java/com/hotsearch/
├── HotsearchApplication.java
├── config/ # Security、限流、JWT 过滤器、@CurrentUserId 解析器
├── controller/ # REST API
├── dto/ # Request/Response records
├── entity/ # JPA 实体(JSON 字段统一走 entity/converter 转换器)
├── exception/ # ApiException 体系(404/400/429/502 统一映射)
├── fetcher/ # 微博热搜抓取(AJAX 优先,HTML 兜底)
├── matcher/ # 订阅规则匹配引擎
├── provider/ # 推送提供者(飞书/钉钉/企微/微信/Telegram/Webhook)
├── repository/ # Spring Data JPA 仓库
├── service/ # 业务逻辑(管线 = Planner 规划 + Executor 执行)
└── util/ # JWT 工具
| 状态码 | 含义 |
|---|---|
| 400 | 请求参数或业务规则不满足(含通道配置缺失) |
| 401 | 未登录或登录已过期 |
| 404 | 资源不存在或不属于当前用户 |
| 429 | 登录尝试过于频繁 |
| 502 | 推送上游(微信/飞书等)调用失败 |
| 500 | 服务器内部错误(细节仅记录在服务端日志) |
本项目基于 MIT License 开源。欢迎提 Issue 与 PR;提交代码前请运行 mvn test 确保测试全部通过。



