# 军事科技每日资讯推送系统 基于大模型的军事/科技新闻采集、评分、整合与推送系统。自动抓取 RSS 订阅源,经 LLM 评分筛选与实体聚类后,生成日报并推送到飞书群,同时提供 Web 归档站点浏览历史推送。 ## 系统架构 ``` ┌───────────────────────────────────────────────────────────────┐ │ Fetch 循环(每 30 分钟) │ │ RSS 抓取 → 中英翻译 → LLM 评分 → 硬约束过滤 → 动态阈值 │ │ → 实体提取 + 角度分类 → 实体归一化 → 实体聚类 │ │ → 广告过滤 → 缓存 → 簇热度计算 → 即时推送(≥90 分) │ │ → 自动清理过期缓存(60 天) │ └──────────────────┬────────────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ Push 循环(每日 08:00) │ │ 推送 1: 🔥 热点速览(簇视图) │ │ 今日速览 + 热点洞察(含[持续跟踪])+ 跨日追踪 + 趋势分析 │ │ 推送 2: 📰 军事科技每日精选(单篇视图) │ │ 网摘 Top3 + 分类概览(5 类 × 5 条) │ │ 推送 3: 🖼️ 网摘图片(PNG 合并长图,图床上传后推送) │ └──────────────────┬────────────────────────────────────────────┘ ↓ ┌───────────────────────────────────────────────────────────────┐ │ Web 归档站点(http://0.0.0.0:8080) │ │ 按日期浏览历史推送:簇视图 + 单篇视图 + 网摘图片 │ │ 支持分类筛选、全文搜索、评分排序 │ └───────────────────────────────────────────────────────────────┘ ``` | 核心功能 | 说明 | |---------|------| | 订阅源管理 | OPML 文件管理 137 个 RSS 源(英文军事 + 中文微信公众号) | | 双语翻译 | 中英自动分离(汉字占比 > 20%),中文零 API 调用,外文并发翻译 | | 三层评分 | 硬约束(非目标 ≤79 / KOL ≤89)+ 时间衰减 + 动态阈值 | | 实体提取 | 5 类实体(人物/机构/装备/事件/地域)+ 6 类角度分类,双层归一化(规则 200+ 别名 + LLM 消歧) | | 实体聚类 | 加权实体重叠 + 并查集,细粒度聚类保留多角度报道,自动命名簇 | | 簇热度 | 四维评分(最高分 + 传播 + 角度 + 优先)+ LLM 精评融合,热度簇提升为热点 | | 簇记忆 | SQLite 持久化已推送簇 ID,24h 内同簇不重复推送 | | 广告过滤 | 四层防御纵深(tag 黑名单 → 动态阈值 → 空角度 → 空实体) | | 增量缓存 | SQLite 三级缓存(文章/网摘/分类摘要),60 天自动清理,二次运行几乎零 token 消耗 | | 飞书推送 | 即时热点推送(≥90 分)+ 每日早报三波(热点速览 + 每日精选 + 网摘图片) | | Web 归档 | Flask 站点,按日期浏览历史推送,支持分类筛选和全文搜索 | | 日志系统 | 终端输出实时写入 `logs/YYYYMMDD-HHmmSS.log`,`[管线]`/`[Web]` 前缀区分来源 | | 双视角洞察 | LLM 一次调用输出精炼摘要 + 结构化洞察(事件脉络/多角度分析/影响与展望) | | 分类概览 | 5 类军事新闻分类(装备技术/地区安全/军事改革/产业观察/其他热点),每类 top 5 | | 网摘图片 | PIL 渲染网摘为 PNG 合并长图,自适应高度 + 动态文本换行,图床 API 上传后推送飞书 | | 反馈闭环 | 用户评分修正记录 + 规则自动生成,修正后的评分自动应用到后续批次 | | 运行监控 | 12 阶段耗时 + API 调用统计 + 源抓取成功率 + 缓存命中率 | ## 快速开始 > 详细指南见 [QUICKSTART.md](QUICKSTART.md) ### 环境要求 - Python 3.10+(或 Docker) - 能访问 OpenAI 兼容 API(DeepSeek / 火山引擎 / OpenAI 等) ### Docker 部署(推荐) ```bash # 1. 准备配置 mkdir -p docker/prompts docker/data docker/logs cp .env docker/.env cp config.json docker/config.json cp -r prompts/* docker/prompts/ # 2. 构建并启动 docker compose up -d --build # 3. 访问 Web 归档站点 # http://localhost:8080 ``` ### 本地安装 ```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 [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` | 查看修正统计数据 | ## 部署 ### Docker(推荐,适用于绿联云 NAS / 任何 Linux 主机) ```bash # 1. 准备配置目录 mkdir -p docker/prompts docker/data docker/logs cp .env docker/.env cp config.json docker/config.json cp -r prompts/* docker/prompts/ # 2. 构建并启动 docker compose up -d --build # ── 运维 ────────────────────────────────────── docker compose logs -f # 查看实时日志 docker compose restart # 重启 docker compose down # 停止并删除容器 docker compose up -d --build # 更新代码后重建并启动 ``` #### 镜像导出(本地打包 → NAS 导入) ```bash # 本地构建并导出 docker compose build docker save -o military-digest.tar my-daily-military-digest:latest # NAS 上导入 docker load -i military-digest.tar # 使用 docker-compose.nas.yml 启动 docker compose -f docker-compose.nas.yml up -d ``` #### 文件映射 | NAS 目录 | 容器内路径 | 用途 | |----------|-----------|------| | `docker/.env` | `/app/.env` | API Key、Webhook | | `docker/config.json` | `/app/config.json` | 调度、评分参数 | | `docker/prompts/` | `/app/prompts/` | LLM 提示词 | | `docker/data/` | `/app/data/` | 运行时数据 | | `docker/logs/` | `/app/logs/` | 运行日志 | ### 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/prompts docker/data docker/logs cp .env docker/.env cp config.json docker/config.json cp -r prompts/* docker/prompts/ # 2. 构建并启动 docker compose up -d --build # ── 运维 ────────────────────────────────────── docker compose logs -f # 查看实时日志 docker compose restart # 重启 docker compose down # 停止并删除容器 docker compose up -d --build # 更新代码后重建并启动 ``` #### 镜像导出(本地打包 → NAS 导入) ```bash # 本地构建并导出 docker compose build docker save -o military-digest.tar my-daily-military-digest:latest # NAS 上导入 docker load -i military-digest.tar # 使用 NAS 专用配置启动 docker compose -f docker-compose.nas.yml up -d ``` #### 文件映射 | NAS 目录 | 容器内路径 | 用途 | |----------|-----------|------| | `docker/.env` | `/app/.env` | API Key、Webhook | | `docker/config.json` | `/app/config.json` | 调度、评分参数 | | `docker/prompts/` | `/app/prompts/` | LLM 提示词 | | `docker/data/` | `/app/data/` | 运行时数据 | | `docker/logs/` | `/app/logs/` | 运行日志 | ## 运维工具 | 脚本 | 平台 | 功能 | |------|:---:|------| | [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/ # fetch-YYYY-MM-DD.json(当日抓取结果) ├── hotalert/ # hotalert-YYYYMMDD-HHmmSS.md(即时推送快讯) ├── cluster/ # cluster-YYYYMMDD-HHmmSS.md(热点速览) ├── digest/ # digest-YYYYMMDD-HHmmSS.md(每日精选) ├── images/ # 网摘 PNG 图片 │ └── YYYYMMDD/ │ ├── webzine_{N}_{timestamp}.png │ └── webzine_combined_{timestamp}.png └── cache/ # article_cache.db(SQLite) ``` | 目录/文件 | 说明 | 保留策略 | |-----------|------|:---:| | `data/fetch/` | 当日 Fetch 结果(含评分、摘要) | 7 天 | | `data/hotalert/` | 军事科技快讯(即时推送) | 7 天 | | `data/cluster/` | 热点速览(簇视图推送) | 7 天 | | `data/digest/` | 军事科技每日精选(单篇视图推送) | 7 天 | | `data/images/` | 网摘 PNG 图片 | 7 天 | | `data/cache/` | SQLite 缓存(文章/簇记忆/反馈) | 60 天自动清理 | | `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 # 一键启动(管线 + Web + 日志) ├── config.json # 用户配置(不入库) ├── .env # API 密钥(不入库) ├── config.json.example # 配置模板 ├── .env.example # 环境变量模板 ├── requirements.txt # Python 依赖 ├── QUICKSTART.md # 快速上手指南 ├── CONFIG.md # 配置参数完整说明 ├── Dockerfile # Docker 镜像构建 ├── docker-compose.yml # Docker Compose 配置(本地) ├── docker-compose.nas.yml # Docker Compose 配置(NAS 部署) ├── .dockerignore # Docker 构建忽略 ├── 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 # 网摘生成板块 ├── web_archive/ # Web 归档站点 │ ├── server.py # Flask 应用 │ ├── data_parser.py # 数据解析 │ ├── static/ # 静态资源 │ └── templates/ # HTML 模板 ├── templates/ # 推送模板 │ ├── cluster_view.md # 簇视图模板 │ ├── article_view.md # 单篇视图模板 │ └── immediate_push.md # 即时推送模板 ├── CHANGELOG.md # 更新日志 └── README.md # 本文件 ``` ## 常见问题 **Q: 如何在 NAS 上部署?** A: 推荐使用 Docker 部署。本地构建镜像导出 → 上传到 NAS 导入 → 使用 `docker-compose.nas.yml` 启动。详见上方「部署 → Docker」章节。 **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: 如何查看运行日志?** A: 本地运行:`logs/` 目录下按时间戳命名的日志文件。Docker 运行:`docker compose logs -f` 或查看 `docker/logs/` 目录。 **Q: 内存/CPU 占用如何?** A: 异步抓取 + 并发控制(默认 10 并发),翻译/评分均分批处理。137 源全量抓取峰值内存约 200MB,日常运行稳定在 100MB 以内。