517 lines
22 KiB
Markdown
517 lines
22 KiB
Markdown
# 军事科技每日资讯推送系统
|
||
|
||
基于大模型的军事/科技新闻采集、评分、整合与推送系统。自动抓取 RSS 订阅源,经 LLM 评分筛选与实体聚类后,生成日报并推送到飞书群。
|
||
|
||
## 系统架构
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────────────┐
|
||
│ Fetch 循环(每 30 分钟) │
|
||
│ RSS 抓取 → 中英翻译 → LLM 评分 → 硬约束过滤 → 动态阈值 │
|
||
│ → 实体提取 + 角度分类 → 实体归一化 → 实体聚类 │
|
||
│ → 广告过滤 → 缓存 → 簇热度计算 → 即时推送(≥90 分) │
|
||
└──────────────────┬────────────────────────────────────────────┘
|
||
↓
|
||
┌───────────────────────────────────────────────────────────────┐
|
||
│ Push 循环(每日 08:00) │
|
||
│ 推送 1: 🔥 热点速览(簇视图) │
|
||
│ 今日速览 + 热点洞察(含[持续跟踪])+ 跨日追踪 + 趋势分析 │
|
||
│ 推送 2: 📰 军事科技每日精选(单篇视图) │
|
||
│ 网摘 Top3 + 分类概览(5 类 × 5 条) │
|
||
│ 推送 3: 🖼️ 网摘图片(PNG 合并长图,图床上传后推送) │
|
||
└───────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
| 核心功能 | 说明 |
|
||
|---------|------|
|
||
| 订阅源管理 | OPML 文件管理 137 个 RSS 源(英文军事 + 中文微信公众号) |
|
||
| 双语翻译 | 中英自动分离(汉字占比 > 20%),中文零 API 调用,外文并发翻译 |
|
||
| 三层评分 | 硬约束(非目标 ≤79 / KOL ≤89)+ 时间衰减 + 动态阈值 |
|
||
| 实体提取 | 5 类实体(人物/机构/装备/事件/地域)+ 6 类角度分类,双层归一化(规则 200+ 别名 + LLM 消歧) |
|
||
| 实体聚类 | 加权实体重叠 + 并查集,细粒度聚类保留多角度报道,自动命名簇 |
|
||
| 簇热度 | 四维评分(最高分 + 传播 + 角度 + 优先)+ LLM 精评融合,热度簇提升为热点 |
|
||
| 簇记忆 | SQLite 持久化已推送簇 ID,24h 内同簇不重复推送 |
|
||
| 广告过滤 | 四层防御纵深(tag 黑名单 → 动态阈值 → 空角度 → 空实体) |
|
||
| 增量缓存 | SQLite 三级缓存(文章/网摘/分类摘要),二次运行几乎零 token 消耗 |
|
||
| 飞书推送 | 即时热点推送(≥90 分)+ 每日早报三波(热点速览 + 每日精选 + 网摘图片) |
|
||
| 双视角洞察 | LLM 一次调用输出精炼摘要 + 结构化洞察(事件脉络/多角度分析/影响与展望) |
|
||
| 分类概览 | 5 类军事新闻分类(装备技术/地区安全/军事改革/产业观察/其他热点),每类 top 5 |
|
||
| 网摘图片 | PIL 渲染网摘为 PNG 合并长图,自适应高度 + 动态文本换行,图床 API 上传后推送飞书 |
|
||
| 反馈闭环 | 用户评分修正记录 + 规则自动生成,修正后的评分自动应用到后续批次 |
|
||
| 运行监控 | 12 阶段耗时 + API 调用统计 + 源抓取成功率 + 缓存命中率 |
|
||
|
||
## 快速开始
|
||
|
||
### 环境要求
|
||
|
||
- Python 3.10+
|
||
- 能访问 OpenAI 兼容 API(DeepSeek / 火山引擎 / OpenAI 等)
|
||
|
||
### 安装
|
||
|
||
```bash
|
||
# 1. 进入项目目录
|
||
cd my-daily
|
||
|
||
# 2. 安装依赖
|
||
pip install -r requirements.txt
|
||
|
||
# 3. 配置环境变量
|
||
cp .env.example .env
|
||
# 编辑 .env,填入 API Key 和 Webhook 地址
|
||
|
||
# 4. 配置系统参数(可选,已有默认值)
|
||
cp config.json.example config.json
|
||
# config.json 已存在时跳过,按需修改调度/评分/源过滤参数
|
||
```
|
||
|
||
### 环境变量(.env)
|
||
|
||
```env
|
||
# OpenAI 兼容接口(必填)
|
||
OPENAI_API_KEY=your_api_key
|
||
OPENAI_API_BASE=https://api.deepseek.com
|
||
OPENAI_MODEL=deepseek-v4-flash
|
||
|
||
# LLM 消歧 + 网摘专用模型(可选,不填则复用 OPENAI_MODEL)
|
||
WEBZINE_MODEL=deepseek-v4-pro
|
||
|
||
# 飞书推送(可选,不填则跳过推送)
|
||
FEISHU_WEBHOOK=your_webhook_url
|
||
|
||
# 图床上传配置(可选,网摘图片通过图床 API 上传)
|
||
IMAGE_HOSTING_PASSWORD=your_image_hosting_password_here
|
||
|
||
# ── 定时计划配置(可选,覆盖 config.json)──
|
||
# FETCH_INTERVAL_MINUTES=30 # RSS 拉取间隔(分钟)
|
||
# FETCH_LOOKBACK_MINUTES=60 # 回溯时间窗口(分钟)
|
||
# PUSH_CRON="0 8 * * *" # 推送定时计划(cron 表达式,多个用逗号分隔)
|
||
# TIMEZONE_HOURS=8 # 时区
|
||
|
||
# ── 评价管线参数覆盖(可选,最高优先级)──
|
||
# HEAT_THRESHOLD=30 # 热度阈值固定值
|
||
# HOT_THRESHOLD=90 # 即时推送分数线
|
||
# CLUSTER_MERGE_THRESHOLD=4 # 聚类合并阈值
|
||
# PRECISE_BLEND_RATIO=0.4 # LLM 精评融合权重
|
||
# MEMORY_WINDOW_HOURS=24 # 簇记忆去重时间窗口
|
||
# CROSS_DAY_MIN_OVERLAP=0.05 # 跨日关联实体重叠阈值
|
||
```
|
||
|
||
> **优先级规则**:`.env` 环境变量 > `config.json` > 源码默认值。详见 [CONFIG.md](CONFIG.md)。
|
||
|
||
### 配置项速查
|
||
|
||
所有参数及调优指南见 **[CONFIG.md](CONFIG.md)**。
|
||
|
||
| 配置节 | 控制环节 | 关键参数 |
|
||
|--------|----------|----------|
|
||
| **`.env`** | 接口/推送/定时/图床/评价覆盖 | `OPENAI_API_KEY`, `FEISHU_WEBHOOK`, `IMAGE_HOSTING_PASSWORD`, `FETCH_INTERVAL_MINUTES`, `PUSH_CRON` |
|
||
| `schedule` | 定时计划 | `fetch_interval_minutes`(30), `push_cron`(0 8 * * *) |
|
||
| `filter` | 过滤推送 | `hot_threshold`(90), `cluster_promotion_offset`(15) |
|
||
| `scoring` | 单篇评分 | `non_target_max_score`(79), `half_life_hours`(12), `min_age_hours`(6) |
|
||
| `cluster` | 聚类成簇 | `merge_threshold`(4), `entity_weights`, `generic_entities` |
|
||
| `heat` | 簇热度 | `score_weight`(0.4), `propagation_cap`(30), `precise_blend_ratio`(0.4) |
|
||
| `memory` | 去重记忆 | `window_hours`(24), `cleanup_days`(7) |
|
||
|
||
## 命令用法
|
||
|
||
### 一键启动(推荐)
|
||
|
||
```bash
|
||
python start.py
|
||
```
|
||
|
||
同时启动数据管线后端(Fetch + Push 循环)和 Web 归档站点(http://0.0.0.0:8080)。所有终端输出实时写入 `logs/YYYYMMDD-HHmmSS.log`,按 Ctrl+C 安全停止所有服务。
|
||
|
||
### main.py 命令
|
||
|
||
```bash
|
||
python main.py <command> [options]
|
||
```
|
||
|
||
| 命令 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `check` | 校验 LLM 接口可达性 | `python main.py check` |
|
||
| `fetch` | 单次抓取 → 翻译 → 评分 → 缓存 | `python main.py fetch --lookback 120` |
|
||
| `test-fetch` | 测试抓取(限定源数量) | `python main.py test-fetch --max 5 --lookback 300` |
|
||
| `push` | 单次推送(含早报/默认两种模式) | `python main.py push` |
|
||
| `rss` | 仅生成 RSS Digest(不推送,打印到终端) | `python main.py rss` |
|
||
| `loop` | 长跑模式(Fetch + Push 双循环并行) | `python main.py loop` |
|
||
| `feedback` | 提交评分修正反馈 | `python main.py feedback --link URL --score 85 --reason "理由"` |
|
||
|
||
### test-fetch / fetch 参数
|
||
|
||
| 参数 | 默认值 | 说明 |
|
||
|------|:---:|------|
|
||
| `--max N` | 5(仅 test-fetch) | 仅拉取前 N 个源 |
|
||
| `--lookback N` | 来自 config | 时间回溯窗口(分钟) |
|
||
|
||
### feedback 参数
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `--link URL` | 需要修正评分的文章链接 |
|
||
| `--score N` | 修正后的分数(0-100) |
|
||
| `--reason "..."` | 修正理由 |
|
||
| `--list` | 查看所有已记录的修正 |
|
||
| `--rules` | 查看已生成的修正规则 |
|
||
| `--stats` | 查看修正统计数据 |
|
||
|
||
## 部署
|
||
|
||
### Linux(systemd)
|
||
|
||
```bash
|
||
sudo bash scripts/setup_systemd.sh # 一键安装
|
||
bash scripts/status.sh # 查看运行状态
|
||
sudo journalctl -u my-daily-fetch -f # 实时日志
|
||
sudo bash scripts/uninstall_systemd.sh # 卸载
|
||
```
|
||
|
||
### Windows(计划任务)
|
||
|
||
```batch
|
||
scripts\setup_service.bat install # 安装为计划任务
|
||
scripts\setup_service.bat start # 手动运行一次
|
||
scripts\setup_service.bat status # 查看任务状态
|
||
scripts\setup_service.bat loop # 前台调试
|
||
scripts\setup_service.bat uninstall # 卸载计划任务
|
||
```
|
||
|
||
### Docker(推荐,适用于绿联云 NAS / 任何 Linux 主机)
|
||
|
||
```bash
|
||
# 1. 准备目录和配置
|
||
mkdir -p docker/data docker/cache
|
||
cp .env docker/.env
|
||
|
||
# 2. 构建并启动
|
||
docker compose up -d --build
|
||
|
||
# ── 运维 ──────────────────────────────────────
|
||
docker compose logs -f # 查看实时日志
|
||
docker compose restart # 重启
|
||
docker compose down # 停止并删除容器
|
||
docker compose up -d --build # 更新代码后重建并启动
|
||
```
|
||
|
||
#### 目录结构(Docker 部署)
|
||
|
||
```
|
||
my-daily/
|
||
├── docker/ # Docker 持久化目录
|
||
│ ├── .env # 配置文件(API Key, Webhook 等)
|
||
│ ├── data/ # 运行时数据(fetch/push/image 文件)
|
||
│ └── cache/ # SQLite 缓存(避免重复消费 API)
|
||
├── Dockerfile # 镜像构建文件
|
||
├── docker-compose.yml # Docker Compose 配置
|
||
└── .dockerignore # 构建忽略文件
|
||
```
|
||
|
||
#### 在绿联云 NAS 上的操作
|
||
|
||
```bash
|
||
# 方案 A:SSH 直接操作(NAS 开启 SSH 后)
|
||
# 将 my-daily 目录上传到 NAS,进入目录执行:
|
||
docker compose up -d --build
|
||
|
||
# 方案 B:绿联云 Docker 管理器(图形界面)
|
||
# 1. 在本机构建镜像并导出:
|
||
docker save -o military-digest.tar military-digest:latest
|
||
|
||
# 2. 将 tar 文件上传到 NAS
|
||
# 3. 在绿联云 Docker > 镜像管理 > 导入镜像
|
||
# 4. 创建容器时挂载卷:
|
||
# - /path/to/docker/.env → /app/.env(只读)
|
||
# - /path/to/docker/data → /app/data
|
||
# - /path/to/docker/cache → /app/cache
|
||
# 5. 设置重启策略:always
|
||
# 6. 启动容器
|
||
```
|
||
|
||
## 运维工具
|
||
|
||
| 脚本 | 平台 | 功能 |
|
||
|------|:---:|------|
|
||
| [scripts/check_sources.py](scripts/check_sources.py) | 通用 | 源连通性检测:HTTP 可达性 + RSS 解析 + 条目时效分布 |
|
||
| [scripts/test_entity_extract.py](scripts/test_entity_extract.py) | 通用 | 实体提取 + 角度分类独立测试 |
|
||
| [scripts/test_normalizer.py](scripts/test_normalizer.py) | 通用 | 实体归一化效果验证 |
|
||
| [scripts/test_llm_disambiguate.py](scripts/test_llm_disambiguate.py) | 通用 | LLM 消歧层独立测试 |
|
||
| [scripts/status.sh](scripts/status.sh) | Linux | 项目状态查看 |
|
||
| [scripts/install.sh](scripts/install.sh) | Linux | 依赖安装 + systemd 服务文件生成 |
|
||
| [scripts/uninstall.sh](scripts/uninstall.sh) | Linux | systemd 服务卸载 |
|
||
|
||
### 源连通性检测
|
||
|
||
```bash
|
||
python scripts/check_sources.py # 全部源
|
||
python scripts/check_sources.py --max 50 # 前 50 个源
|
||
python scripts/check_sources.py --failed-only # 仅显示失败源
|
||
python scripts/check_sources.py --show-urls # 显示 URL
|
||
python scripts/check_sources.py --concurrency 20 # 自定义并发数
|
||
```
|
||
|
||
## 数据与输出
|
||
|
||
| 目录/文件 | 说明 | 保留策略 |
|
||
|-----------|------|:---:|
|
||
| `data/fetch-YYYY-MM-DD.json` | 当日 Fetch 结果(含评分、摘要) | 7 天 |
|
||
| `data/hotalert-YYYYMMDD-HHmmSS.md` | 军事科技快讯(即时推送) | 7 天 |
|
||
| `data/cluster-YYYYMMDD-HHmmSS.md` | 热点速览(簇视图推送) | 7 天 |
|
||
| `data/digest-YYYYMMDD-HHmmSS.md` | 军事科技每日精选(单篇视图推送) | 7 天 |
|
||
| `data/images/YYYYMMDD/` | 网摘 PNG 图片 | 7 天 |
|
||
| `data/article_cache.db` | SQLite 三级缓存(文章/网摘/分类摘要) | 7 天自动清理 |
|
||
| `logs/YYYYMMDD-HHmmSS.log` | 运行日志(终端输出完整记录) | 手动清理 |
|
||
|
||
## 评价管线详解
|
||
|
||
从 RSS 抓取到即时推送,文章经历 **12 个步骤**,分属两个层面:单篇评分层和簇级评价层。
|
||
|
||
### 第一层:单篇评分
|
||
|
||
#### 步骤 1 — LLM 批量评分
|
||
|
||
调用 `score_batch()` 对每篇文章打分(0-100),同时产出 `tags` 和 `summary`。
|
||
|
||
| 配置项 | 位置 | 默认值 | 说明 |
|
||
|--------|------|:---:|------|
|
||
| `max_prompt_chars` | `config.json → llm` | 10000 | 单批次 Prompt 上限,超限自动拆分 |
|
||
| `max_concurrent_batches` | `config.json → llm` | 3 | LLM 并发批次数 |
|
||
| Prompt | `prompts/score_batch.md` | — | 含核心约束:非军事≤79、KOL≤89、90+需官方首发 |
|
||
|
||
#### 步骤 2 — 硬约束过滤
|
||
|
||
`apply_hard_constraints()` 对 LLM 评分施加上限:
|
||
|
||
| 约束 | 阈值 | 作用 |
|
||
|------|:---:|------|
|
||
| 非目标域名(YouTube/Twitter/B站/微博等) | **≤79** | 社交媒体来源不可信 |
|
||
| KOL 域名(同上) | **≤89** | 个人账号非官方首发 |
|
||
|
||
> 配置:`config.json → scoring.non_target_max_score` / `kol_max_score`
|
||
|
||
#### 步骤 3 — 时间衰减
|
||
|
||
`apply_time_decay()` 指数衰减旧文章分数:
|
||
|
||
```
|
||
有效年龄 = max(0, 当前时间 - 发布时间 - min_age_hours)
|
||
衰减因子 = 0.5 ^ (有效年龄 / half_life_hours)
|
||
最终分数 = 原分数 × 衰减因子
|
||
```
|
||
|
||
| 参数 | 默认值 | 说明 |
|
||
|------|:---:|------|
|
||
| `half_life_hours` | 12 | 半衰期 |
|
||
| `min_age_hours` | 6 | 6 小时内不衰减 |
|
||
|
||
#### 步骤 4 — 动态阈值
|
||
|
||
`calculate_dynamic_threshold()` 筛选合格文章:
|
||
|
||
```
|
||
阈值 = 均值 + 1.5 × 标准差
|
||
clamp[40, 90]
|
||
```
|
||
|
||
只有 `score ≥ 阈值` 的文章进入下一步实体提取。
|
||
|
||
---
|
||
|
||
### 第二层:簇级评价
|
||
|
||
#### 步骤 5 — 实体提取 + 角度分类
|
||
|
||
`batch_extract_all()` 对合格文章提取实体和角度,两个 LLM 调用并发执行。
|
||
|
||
| 类别 | Prompt | 输出 |
|
||
|------|--------|------|
|
||
| 实体(5 类) | `prompts/extract_entities.md` | `entities: {person, org, equipment, event, location}` |
|
||
| 角度(6 类) | `prompts/classify_angle.md` | `reporting_angle: 政策发布/技术突破/战略分析/舆论反应/冲突事件/人物动态` |
|
||
|
||
#### 步骤 6 — 实体归一化
|
||
|
||
`normalize_entries_async()` 双层归一化:
|
||
|
||
| 层 | 方式 | 成本 | 示例 |
|
||
|----|------|:---:|------|
|
||
| 规则映射 | `entity_aliases.json`(200+ 别名) | 零 | `PL-21 → 霹雳-21`、`DARPA → 美国国防高级研究计划局` |
|
||
| LLM 消歧 | `WEBZINE_MODEL` 批量判断未知别名 | API | `Strait of Hormuz → 霍尔木兹海峡` |
|
||
|
||
#### 步骤 7 — 聚类成簇
|
||
|
||
`cluster_articles()` 加权实体重叠 + 并查集:
|
||
|
||
| 实体类别 | 权重 | 合并条件 |
|
||
|----------|:---:|------|
|
||
| equipment / event | **3**(核心) | 共享即直接合并(泛化实体黑名单内的除外) |
|
||
| org / person | **2** | 需累计权重 ≥ 4 |
|
||
| location | **1** | 需累计权重 ≥ 4 |
|
||
|
||
> 泛化黑名单(不触发直接合并):`无人机`、`导弹`、`雷达`、`坦克`、`战机`、`军舰` 等 23 个类别词
|
||
|
||
#### 步骤 8 — 启发式热度计算
|
||
|
||
`calculate_cluster_heat()` 四维评分(0-100):
|
||
|
||
```
|
||
热度 = min(100,
|
||
最高分 × 0.4 × 时间衰减
|
||
+ min(报道数 × log(来源多样性) × 3, 30)
|
||
+ 角度数/6 × 20
|
||
+ min(90+文章数 × 5, 10)
|
||
)
|
||
```
|
||
|
||
#### 步骤 9 — 热度阈值
|
||
|
||
`calculate_hotspot_threshold()` 动态阈值:
|
||
|
||
```
|
||
热度阈值 = 均值 + multiplier × σ
|
||
clamp[clamp_min, clamp_max]
|
||
```
|
||
|
||
| 配置 | 位置 | 默认值 | 效果 |
|
||
|------|------|:---:|------|
|
||
| `threshold_clamp_min` | `config.json → heat` | 35 | 阈值下限 |
|
||
| `threshold_clamp_max` | `config.json → heat` | 80 | 阈值上限 |
|
||
| `threshold_multiplier` | `config.json → heat` | 1.5 | σ 乘数 |
|
||
| `HEAT_THRESHOLD` | `.env` | — | **固定覆盖**(最高优先级) |
|
||
|
||
#### 步骤 10 — LLM 精评融合
|
||
|
||
`precise_score_clusters()` 对 Top 30 簇调用 LLM 重新精评(军事价值40% + 时效25% + 信息密度20% + 传播15%),与启发式 6:4 融合:
|
||
|
||
```
|
||
融合热度 = 启发式 × 0.6 + 精评分 × 0.4
|
||
```
|
||
|
||
> Prompt:`prompts/precise_heat.md`,失败时回退纯启发式热度。
|
||
|
||
#### 步骤 11 — 热点识别
|
||
|
||
热点文章 = **三类并集**:
|
||
|
||
| 来源 | 条件 |
|
||
|------|------|
|
||
| 直接热点 | 单篇 score ≥ `hot_threshold`(90) |
|
||
| 簇提升 | 所在簇热度 ≥ 阈值,且单篇 ≥ `hot_threshold - 15`(75) |
|
||
|
||
#### 步骤 12 — 簇记忆去重
|
||
|
||
`cluster_memory.is_recently_pushed()` 检查簇是否在 24h 内已推送,已推送则跳过。
|
||
|
||
> 存储:SQLite 表 `cluster_memory`,7 天自动清理。
|
||
|
||
---
|
||
|
||
### 配置速查
|
||
|
||
| 参数 | 位置 | 默认值 | 作用环节 |
|
||
|------|------|:---:|------|
|
||
| `hot_threshold` | `config.json → filter` | 90 | 步骤 11:直接热点线 |
|
||
| `non_target_max_score` | `config.json → scoring` | 79 | 步骤 2:非目标封顶 |
|
||
| `kol_max_score` | `config.json → scoring` | 89 | 步骤 2:KOL 封顶 |
|
||
| `half_life_hours` | `config.json → scoring` | 12 | 步骤 3:衰减半衰期 |
|
||
| `dynamic_threshold_multiplier` | `config.json → scoring` | 1.5 | 步骤 4:σ 乘数 |
|
||
| `threshold_clamp_min` | `config.json → heat` | 35 | 步骤 9:热度下限 |
|
||
| `threshold_multiplier` | `config.json → heat` | 1.5 | 步骤 9:热度 σ 乘数 |
|
||
| `HEAT_THRESHOLD` | `.env` | — | 步骤 9:固定覆盖 |
|
||
|
||
## 项目文件说明
|
||
|
||
```text
|
||
my-daily/
|
||
├── main.py # 入口 + 双循环架构
|
||
├── start.py # 一键启动(含日志记录)
|
||
├── config.json # 用户配置(不入库)
|
||
├── .env # API 密钥(不入库)
|
||
├── config.json.example # 配置模板
|
||
├── .env.example # 环境变量模板
|
||
├── requirements.txt # Python 依赖
|
||
├── CONFIG.md # 配置参数完整说明
|
||
├── Dockerfile # Docker 镜像构建
|
||
├── docker-compose.yml # Docker Compose 配置
|
||
├── .dockerignore # Docker 构建忽略
|
||
├── logs/ # 运行日志(YYYYMMDD-HHmmSS.log)
|
||
├── prompts/ # LLM 提示词(10 个)
|
||
│ ├── score_batch.md # 批量评分
|
||
│ ├── digest.md # RSS Digest 生成
|
||
│ ├── immediate_push.md # 即时推送快讯
|
||
│ ├── webzine.md # 参考消息风格网摘
|
||
│ ├── category_overview.md # 分类概览
|
||
│ ├── extract_entities.md # 实体提取(5 类)
|
||
│ ├── classify_angle.md # 角度分类(6 类)
|
||
│ ├── precise_heat.md # 热点精评(四维评分)
|
||
│ ├── cluster_insight.md # 双视角洞察
|
||
│ └── cluster_summary.md # 轻量簇摘要
|
||
├── resources/
|
||
│ └── rss_feeds.opml # RSS 订阅源(137 个源)
|
||
├── templates/ # 推送模板
|
||
│ ├── cluster_view.md # 簇视图模板
|
||
│ ├── article_view.md # 单篇视图模板
|
||
│ └── immediate_push.md # 即时推送模板
|
||
├── scripts/ # 运维 + 测试脚本
|
||
│ ├── check_sources.py # 源连通性检测
|
||
│ ├── setup_systemd.sh # Linux systemd 安装
|
||
│ ├── setup_service.bat # Windows 计划任务管理
|
||
│ ├── install.sh / uninstall.sh
|
||
│ └── status.sh
|
||
├── systemd/ # systemd 模板
|
||
├── src/ # 源代码
|
||
│ ├── config.py # 配置加载 + OPML 解析 + 环境变量覆盖
|
||
│ ├── fetcher.py # RSS 异步抓取
|
||
│ ├── translator.py # 中英分离翻译管线
|
||
│ ├── llm.py # LLM 调用(评分/摘要/洞察/精评)
|
||
│ ├── scoring.py # 评分后处理(约束/衰减/阈值)
|
||
│ ├── cache.py # SQLite 三级缓存
|
||
│ ├── storage.py # 文件存储 + Sentinel 分段
|
||
│ ├── monitor.py # 运行监控统计
|
||
│ ├── logger.py # 日志系统
|
||
│ ├── processor.py # HTML → Markdown
|
||
│ ├── utils.py # 通用工具函数
|
||
│ ├── markdown_utils.py # Markdown 解析工具
|
||
│ ├── renderer.py # 模板渲染
|
||
│ ├── generators/ # 图片生成模块
|
||
│ │ ├── image_renderer.py # 网摘 PNG 图片渲染
|
||
│ │ └── get_chinese_font.py # 中文字体管理
|
||
│ ├── processors/ # 处理管线
|
||
│ │ ├── entity_extractor.py # 实体提取 + 角度分类
|
||
│ │ ├── entity_normalizer.py # 实体归一化(双层)
|
||
│ │ ├── entity_aliases.json # 别名映射表
|
||
│ │ ├── cluster_engine.py # 实体聚类引擎
|
||
│ │ ├── cluster_memory.py # 簇记忆系统
|
||
│ │ ├── heat_calculator.py # 簇热度计算
|
||
│ │ ├── rank_engine.py # 排序引擎
|
||
│ │ ├── trend_analyzer.py # 趋势分析
|
||
│ │ ├── feedback.py # 反馈闭环
|
||
│ │ └── cross_day.py # 跨日关联
|
||
│ ├── integrators/
|
||
│ │ └── summary_integrator.py # 摘要整合编排
|
||
│ ├── utils/
|
||
│ │ └── prompt_checker.py # Prompt 防退化检查器
|
||
│ ├── push/ # 推送模块
|
||
│ │ ├── feishu.py # 飞书 Webhook 推送
|
||
│ │ └── image_hosting.py # 图床上传模块
|
||
│ └── sections/ # 内容板块
|
||
│ ├── rss/section.py # RSS Digest 板块
|
||
│ └── webzine/section.py # 网摘生成板块
|
||
├── CHANGELOG.md # 更新日志
|
||
├── PROGRESS.md # 开发进展追踪
|
||
└── README.md # 本文件
|
||
```
|
||
|
||
## 常见问题
|
||
|
||
**Q: 为什么英文源抓不到文章?**
|
||
A: 英文军事源(如 The War Zone、Defense One)更新频率低,可能 2-3 天无新文章。中文微信公众号源更新频繁,扩大 `--lookback` 可覆盖更多时间窗口。
|
||
|
||
**Q: 如何添加/屏蔽订阅源?**
|
||
A: OPML 文件管理为主。临时追加用 `config.json` 的 `sources.add`,屏蔽用 `sources.block` 或 `sources.block_domains`。支持 `*.domain.com` 通配。
|
||
|
||
**Q: 如何修改定时计划?**
|
||
A: 在 `.env` 中设置 `FETCH_INTERVAL_MINUTES`(拉取间隔)和 `PUSH_CRON`(推送定时,cron 表达式),重启服务即可生效。
|
||
|
||
**Q: 内存/CPU 占用如何?**
|
||
A: 异步抓取 + 并发控制(默认 10 并发),翻译/评分均分批处理。137 源全量抓取峰值内存约 200MB,日常运行稳定在 100MB 以内。 |