docs(deploy): document PV/UV stats and real client IP via nginx realip
This commit is contained in:
1 parent
b215f8eb09
commit
ff5e05998a
11 files changed
+308
-6
No files matched your search
+32
-1
@@ -217,6 +217,7 @@ PRAGMA synchronous = NORMAL;
|
||||
│ ├── scheduler.py # 内置任务调度
|
||||
│ ├── logging_json.py # 脱敏 JSON 日志
|
||||
│ ├── classify.py # 标题归一化、时长解析与打分
|
||||
│ ├── client_ip.py # 来源 IP 提取、路由归一化、机器人判定(纯函数)
|
||||
│ ├── video_ref.py # BV/av/URL/b23.tv 引用解析(纯函数)
|
||||
│ ├── timeutil.py # 上海时区与每日时间
|
||||
│ ├── bilibili/
|
||||
@@ -238,8 +239,12 @@ PRAGMA synchronous = NORMAL;
|
||||
│ └── web/ # P2 只读看板
|
||||
│ ├── server.py # HTTP、路由、鉴权、静态资源
|
||||
│ ├── queries.py # 看板 SQL 与数据整形
|
||||
│ ├── visits.py # 访问统计内存缓冲与批量落库
|
||||
│ └── static/ # 原生 JS/CSS、ECharts、预览页面
|
||||
│
|
||||
├── deploy/
|
||||
│ └── nginx/ # 反代示例:真实来源 IP(realip)与站点配置
|
||||
│
|
||||
├── tools/
|
||||
│ ├── seed_preview_db.py # 复制真实库并回填 7 天预览数据
|
||||
│ └── import_fans_csv.py # 从 B 站粉丝历史 CSV 回填 up_stat
|
||||
@@ -329,6 +334,7 @@ PRAGMA synchronous = NORMAL;
|
||||
|
||||
- `snapshot` 主键为 `(stat_date, aid)`,保证同日幂等;
|
||||
- `up_stat` 主键为 `(stat_date, mid)`;
|
||||
- `visit` 访问统计表主键为 `(stat_date, ip, path)`,`hits` 累加;数据先落内存缓冲、批量 upsert,`PV = SUM(hits)`、`UV = COUNT(DISTINCT ip)`;
|
||||
- `folder` / `folder_resource` 保留为历史数据与重排序参考,**不再由服务写入**;
|
||||
- `up_blacklist` 只在发现任务中生效,不影响已入库视频;
|
||||
- `seen_aid` 永久保留搜索去重标记,候选过期删除后也不重复通知;
|
||||
@@ -499,6 +505,7 @@ P3 实现说明:
|
||||
### 9.1 API 原则
|
||||
|
||||
- P2 看板**只读**:业务接口只注册 GET,写方法统一返回 `405`;
|
||||
- 仅显式放行两个 POST 端点:`POST /login`(建立会话)与 `POST /api/visit`(访问统计埋点);二者都不修改业务数据,其余 POST/PUT/PATCH/DELETE 仍统一 `405`;
|
||||
- 数据管理(入库、忽略、拉黑、移出库、移除黑名单)继续通过 Telegram、CLI 或数据库完成;
|
||||
- `/api/health` 和 `/api/session` 可匿名;
|
||||
- 首页、榜单、视频/UP、粉丝页面和接口访客可见;
|
||||
@@ -525,6 +532,8 @@ P3 实现说明:
|
||||
| `GET` | `/api/candidates` | 候选池(只读) |
|
||||
| `GET` | `/api/system` | 最近任务、下次任务、备份、黑名单 |
|
||||
| `GET` | `/api/about` | 数据说明页当前口径(配置阈值、权重、覆盖度;无凭据) |
|
||||
| `POST` | `/api/visit` | 访问统计埋点(匿名):归一化路径后写内存缓冲,定期批量落库 |
|
||||
| `GET` | `/api/stats` | 访问统计(需登录):每日 PV/UV 序列、Top 页面,合并未落库缓冲 |
|
||||
|
||||
### 9.2 页面
|
||||
|
||||
@@ -538,7 +547,7 @@ P3 实现说明:
|
||||
| UP 页 | 该 UP 的头像、mid、首RE时间、最近发布时间、全部视频、聚合趋势、单视频对比、总时长与播放·小时、入库时与当前粉丝数。 |
|
||||
| 粉丝页 | 粉丝总数、日增、7 日净增、累计增长(标注起始日期);支持预设和自选日期,范围超过一年时按每月峰值日期聚合;最近记录默认 14 天并显示“较上一成功日”增量;不叠加视频数据。 |
|
||||
| 候选池 | 待确认候选、规则命中、剩余保留时间;操作指向 Telegram/CLI。 |
|
||||
| 系统状态 | 最近扫描、同步、快照、下次运行、备份、鉴权和黑名单。 |
|
||||
| 系统状态 | 最近扫描、同步、快照、下次运行、备份、鉴权、黑名单与访问统计(近 30 天 PV/UV 与 Top 页面)。 |
|
||||
|
||||
### 9.3 预览模式
|
||||
|
||||
@@ -550,6 +559,15 @@ P3 实现说明:
|
||||
- 重新生成预览库前必须停止预览服务,避免 Windows 文件占用;
|
||||
- 第 9 轮起本地不再保留 `data/app.db` 真实副本;重新生成预览时用 `--source` 指向 `data/backup/` 中的真实库备份(如 `app-local-before-reseed-20261101.db`)。
|
||||
|
||||
### 9.4 访问统计与真实来源 IP
|
||||
|
||||
- 前端在整页加载与站内路由切换时通过 `navigator.sendBeacon("/api/visit")` 上报路径(`sort`/筛选等同路径重渲染不重复计数);
|
||||
- 服务端 `reaction_board/web/visits.py` 把上报按 `(日期, IP, 路由)` 聚合到内存缓冲,后台线程每 `web.track.flush_seconds`(默认 60 秒)批量 upsert 到 `visit` 表;`server_close()` 时做最后一次 flush;
|
||||
- `/api/stats` 合并未落库缓冲,因此系统页基本实时;`keep_days` 到期数据由后台按日清理;
|
||||
- 真实 IP 由 nginx 用 `realip` 模块按 CDN 网段归一化后写入 `X-Real-IP`;应用(`reaction_board/client_ip.py`)仅在 socket 对端属于 `web.track.trusted_proxies` 时采信请求头,否则回退对端,避免直连请求伪造 `CF-Connecting-IP`/`EO-Connecting-IP`/`X-Forwarded-For`;
|
||||
- 直连公网 EIP、Cloudflare、EdgeOne 三种来源的 nginx 配置与网段刷新脚本见 `deploy/nginx/`;配置项见 README 的 `web.track` 说明;
|
||||
- 进程被强杀时最多丢失一个刷新周期的上报(可接受)。
|
||||
|
||||
---
|
||||
|
||||
## 10. 热度与趋势口径
|
||||
@@ -632,6 +650,8 @@ uv run python tests/test_moves.py
|
||||
- Telegram 用户与 chat ID 授权校验;
|
||||
- 看板查询的筛选、分页、增长冷启动与状态过滤;
|
||||
- 只读路由、鉴权、静态资源路径穿越和预览标记校验;
|
||||
- 来源 IP 提取(直连 EIP/Cloudflare/EdgeOne、不可信对端伪造、IPv6、带端口、回退)与路由归一化、机器人判定;
|
||||
- 访问统计内存缓冲(聚合、跨日、单键上限、flush 幂等、写失败并回、保留期清理)与 `POST /api/visit`、`GET /api/stats` 契约;
|
||||
- 预览库生成的确定性、单调性、异常样本与真实库隔离;
|
||||
- 粉丝历史 CSV 解析、同日去重、缺口计数与幂等/替换回填;
|
||||
- UP 粉丝快照:首次写入不可覆盖、同轮去重、失败不中断、`live_since` 实时/回填标记、`backfill` 的 dry-run 与 limit;
|
||||
@@ -759,6 +779,17 @@ uv run python tests/test_moves.py
|
||||
- `/api/ups` 返回 `up_face` 与 `follower_latest`,`/api/ups/{mid}` 返回 `up_face`;
|
||||
- 自动化测试更新:`test_migrations.py`、`test_database.py`、`test_web_queries.py`、`test_bilibili_client.py`、`test_library.py`、`test_snapshot.py`、`web_fixtures.py`。
|
||||
|
||||
### 第 12 轮:访问统计(PV/UV)✅(2026-11-01)
|
||||
|
||||
- 迁移 v7:新增 `visit(stat_date, ip, path, hits, first_at, last_at)` 聚合表;
|
||||
- `reaction_board/client_ip.py`:来源 IP 提取、路由归一化与机器人判定纯函数(三种来源 + 伪造防护);
|
||||
- `reaction_board/web/visits.py`:访问上报先落内存缓冲,后台每分钟批量 upsert,支持单键上限与保留期清理,关闭时最后一次 flush;
|
||||
- 前端 `navigator.sendBeacon("/api/visit")` 埋点;Web 只读边界放宽为显式 POST 白名单(`/api/visit` + `/login`);
|
||||
- `config.json` 新增 `web.track`(`enabled`/`header_order`/`trusted_proxies`/`count_bots`/`flush_seconds`/`keep_days`/`max_hits_per_ip_path_per_day`);
|
||||
- 系统状态页展示近 30 天 PV/UV 与 Top 页面(`GET /api/stats`,需登录,合并未落库缓冲);
|
||||
- `deploy/nginx/` 提供直连 EIP / Cloudflare / EdgeOne 的 realip 与站点配置、网段刷新脚本和说明;
|
||||
- 自动化测试新增 `tests/test_client_ip.py`、`tests/test_visits.py`,并扩展 `test_config.py`、`test_web_queries.py`、`test_web_server.py`、`test_migrations.py` 等。
|
||||
|
||||
### P4:可选部署
|
||||
|
||||
- 反向代理、TLS、远程访问鉴权;
|
||||
|
||||
Reference in new issue
Block a user