diff --git a/README-1.md b/README-1.md new file mode 100644 index 0000000..5c561b5 --- /dev/null +++ b/README-1.md @@ -0,0 +1,286 @@ +# 🪖 军事科技每日摘要系统 V3 + +完整的军事科技 RSS 抓取 + AI 智能分析 + 增量缓存 + 运行监控系统 + +## ✨ 完整功能 + +### 📥 数据抓取 +- 🔗 可配置 RSS 源直抓(rss_feeds.txt 管理,支持 100+ 源) +- ⏰ 24 小时时间窗口过滤 +- 🔄 同源标题去重(保留跨源对同一事件的不同报道) +- ⚡ ThreadPoolExecutor 并发抓取,内置失败重试 + +### 🗄️ 增量缓存 +- 💾 SQLite 本地缓存:文章翻译/AI分析结果持久化 +- 📰 网摘文本缓存:再次运行零 token 消耗 +- 🏷️ 分类介绍缓存:按日期+分类独立存储 +- 🧹 自动过期清理(7天)+ 表结构自动迁移 + +### 🌐 智能翻译 +- 🔍 自动识别外文文章 +- 📝 分步翻译:先标题 → 再正文(仅通过筛选的文章) +- ⚡ 并发翻译(ThreadPoolExecutor) + +### 🔑 关键词筛选 +- 🎯 44 个军事科技专业关键词库 +- 📊 命中数排序,文章 >15 篇时自动过滤 + +### 🤖 AI 智能分析 +- ⭐ 多维度评分(技术35% + 战略30% + 信息20% + 时效15%) +- 📋 自动分类:今日必看 / 装备动态 / 地区冲突 / 战略政策 +- ✍️ 每篇文章 AI 智能摘要(80-120字) +- 🔮 分类深度洞察分析(每类50字综述) +- 🏆 TOP3 必看深度分析 +- ⚡ 批量并发评分 + 分类 + +### 🖼️ 图片生成 +- 📄 3800px 超长网摘图片 +- 🎨 军事主题视觉设计 +- 📊 包含TOP3完整内容 +- 💾 自动保存PNG文件 + +### 📊 运行监控 +- ⏱ 各阶段耗时统计,自动输出结构化报表 +- 🤖 API 调用量/token 按用途和模型分组统计 +- 📰 源抓取成功/失败率一目了然 +- 📡 文章统计 + 缓存命中率 + +## 🚀 快速开始 + +### 方式一:本地直接运行(推荐) + +```bash +# 1. 安装依赖 +pip install -r requirements.txt + +# 2. 配置环境 +cp config/.env.example config/.env +vim config/.env +# 编辑 OPENAI_API_KEY + +# 3. 运行 +make local +``` + +### 方式二:Docker 部署 + +```bash +# 1. 克隆或解压 +cd military-digest-v3 + +# 2. 配置环境 +cp config/.env.example config/.env +vim config/.env +# 编辑 OPENAI_API_KEY + +# 3. 构建镜像 +make build + +# 4. 测试运行 +make run-once + +# 5. 安装定时任务 +make install-cron +``` + +## 📁 目录结构 + +``` +military-digest-v3/ +├── scripts/ +│ ├── military_daily_report_v3.py # 主入口 — 流程编排 +│ └── modules/ # 功能模块包 +│ ├── __init__.py # 包初始化 + 统一导出 +│ ├── config.py # 配置模块:常量 + AI配置加载 +│ ├── utils.py # 工具函数:语言检测/HTML清洗/AI调用/换行 +│ ├── rss_fetcher.py # RSS抓取:12源 × 6线程并发 +│ ├── translator.py # 翻译处理:中英分离 + 并发翻译 +│ ├── keyword_filter.py # 关键词筛选:49词命中排序 +│ │ ├── ai_analyzer.py # AI分析:评分/分类/摘要/洞察/网摘生成 +│ │ ├── cache.py # SQLite缓存:文章/网摘/分类介绍增量缓存 +│ │ ├── monitor.py # 运行监控:阶段耗时/API/AI token调用统计 +│ │ ├── pusher.py # 推送模块:企业微信/飞书 webhook 推送 +│ │ ├── image_generator.py # 图片生成:TOP3合并3800px长图 +│ └── get_chinese_font.py # 字体模块:跨系统中文字体适配 +├── config/ +│ ├── config.json # 系统配置 +│ └── .env.example # 环境变量示例 +├── output/ # 输出目录 +│ ├── military_report_YYYYMMDD.md # 完整报告(Markdown格式,支持链接、样式) +│ ├── military_webzine_YYYYMMDD.txt # TOP3网摘文本 +│ └── military_webzine_YYYYMMDD.png # TOP3网摘合并长图 +├── logs/ # 日志目录 +├── Dockerfile +├── docker-compose.yml +├── Makefile +└── README.md +``` + +## 🧩 模块架构 + +``` +military_daily_report_v3.py ← 主入口(流程编排) + ├── config.py ← 配置常量,零依赖 + ├── logger.py ← 统一日志模块 + ├── cache.py ← SQLite增量缓存,自动迁移 + ├── monitor.py ← 运行监控统计 + ├── pusher.py ← 企业微信/飞书推送 + ├── rss_fetcher.py ← 依赖 config + utils + monitor + ├── translator.py ← 依赖 utils + ├── keyword_filter.py ← 依赖 config + ├── ai_analyzer.py ← 依赖 config + utils + ├── image_generator.py ← 依赖 utils + get_chinese_font + └── get_chinese_font.py ← 零依赖 +``` + +### 各模块职责 + +| 模块 | 行数 | 职责 | 对外导出 | +|------|------|------|----------| +| `config.py` | 90 | RSS源、关键词库、评分维度、分类定义、AI配置加载 | `RSS_FEEDS`, `WECHAT_SOURCES`, `KEYWORDS`, `SCORE_DIMENSIONS`, `CATEGORIES`, `load_ai_config()` | +| `utils.py` | 130+ | 语言检测、HTML清理、时间解析、AI API封装(含监控钩子)、文本换行 | `is_chinese()`, `clean_html()`, `extract_content()`, `parse_pub_time()`, `call_ai()`, `wrap_text()` | +| `rss_fetcher.py` | 100+ | 多线程并行抓取RSS源(MAX_THREADS并发,含2次重试+监控上报) | `fetch_all_feeds()` | +| `translator.py` | 150+ | 中英文分离 + 标题/正文分步AI并发翻译 | `batch_translate_titles()`, `batch_translate_contents()` | +| `keyword_filter.py` | 23 | 44关键词命中计数 → 排序 → Top15筛选 | `keyword_filter()` | +| `ai_analyzer.py` | 240+ | 四维度评分、智能分类、中文摘要、分类洞察、《参考消息》风格网摘生成 | `score_and_classify_article()`, `calculate_weighted_score()`, `generate_category_overview()`, `generate_webzine_for_article()`, `batch_score_and_classify_articles()` | +| `cache.py` | 310+ | SQLite增量缓存:文章处理结果+网摘+分类介绍,支持自动迁移+过期清理+断点续跑 | `get_cache()`, `get_article()`, `save_article()`, `save_article_webzine()`, `get_category_summary()`, `save_category_summary()` | +| `monitor.py` | 160+ | 运行时监控:阶段耗时/AI API调用量+token/源成功率/缓存命中率,结束自动输出报表 | `get_monitor()`, `monitor.stage()`, `monitor.report()` | +| `pusher.py` | 130+ | 企业微信文本/图片/Markdown推送 + 飞书文本推送,主流程末自动触发,失败优雅降级 | `send_daily_push()`, `push_wechat_text()`, `push_wechat_image()`, `push_feishu_text()` | +| `image_generator.py` | 220 | 网摘文本渲染为PNG图片(单篇 + TOP3合并长图) | `create_webzine_image()`, `create_combined_webzine_image()` | +| `get_chinese_font.py` | 50 | 跨系统中文字体自动匹配,支持Windows/Linux/macOS,内置开源字体可选 | `get_chinese_font(size, bold)` | + +## ⚙️ 配置说明 + +### 环境变量 (.env) + +| 配置项 | 说明 | 默认值 | +|--------|------|--------| +| OPENAI_API_KEY | OpenAI API 密钥 | - | +| OPENAI_API_BASE | API 地址 | https://api.openai.com/v1 | +| OPENAI_MODEL | AI 分析模型 | gpt-4o-mini | +| WEBZINE_MODEL | 网摘专用模型 | deepseek-v3.2-250518 | + +### config.json 配置项 + +| 配置项 | 说明 | 默认值 | +|--------|------|--------| +| time_window_hours | 时间窗口(小时) | 12 | +| max_articles | 最多保留文章数 | 15 | +| top3_count | TOP3 必看文章数 | 3 | +| wechat_target | 微信接收者ID | - | +| wechat_account | 微信机器人账号 | - | +| enable_wechat_push | 开启微信推送 | true | +| enable_feishu_push | 开启飞书推送 | false | +| enable_image_gen | 开启图片生成 | true | +| enable_txt_gen | 开启TXT文件生成 | true | + +### rss_feeds.txt 订阅源配置 +所有RSS源都在`config/rss_feeds.txt`文件中管理,不需要修改代码即可增删订阅源: +- 格式:每行 `源名称|RSS地址` +- 以`#`开头的行是注释,会自动忽略 +- 空行会自动跳过 +- 修改后直接运行程序,无需重启或改代码 +- ✅ 容错保障:文件不存在、为空或格式错误时,自动回退使用内置的12个默认源,不会影响程序运行 +- 支持所有标准RSS/Atom格式,中英文源无需区分,系统自动识别翻译 + +## ⏰ 定时任务 + +### 方式一:宿主机 crontab + +```bash +make install-cron +# 或手动添加 +crontab -e +# 加入:0 8 * * * cd /path/to/military-digest-v3 && python3 scripts/military_daily_report_v3.py >> logs/cron.log 2>&1 +``` + +### 方式二:Docker Cron + +```bash +docker-compose --profile cron up -d +``` + +## 🔍 RSS 源列表 + +1. Defense One - 美国防务新闻 +2. NEWUAS - 无人机系统新闻 +3. Seapower - 海军力量杂志 +4. The War Zone - 战区军事分析 +5. 国防科技要闻 +6. 战略前沿技术 +7. 无人机邦 +8. 浮空飞行器 +9. 海鹰资讯 +10. 渊亭防务 +11. 电波之矛 +12. 龙牙的一座山 + +## 📊 输出示例 + +``` +🪖 军事科技每日摘要 +📅 2026年05月12日 | 共收录 12 篇 + +==================== +🔥 今日必看 TOP3 +==================== + +1.【美军MQ-9无人机测试发射激光制导火箭弹】 + ⭐ 综合评分:9.2/10 + 📰 来源:The War Zone + 📝 摘要:美国通用原子公司联合美空军在内华达测试场完成... + 🔮 深度洞察:低成本改装令察打无人机获得反无人机能力... + 🔗 阅读原文:... + +... +``` + +## 🔄 数据流程 + +``` +main() + ├── Step 1: RSS 并行抓取(ThreadPoolExecutor × MAX_THREADS 并发,内置重试) + ├── Step 2: 24小时时间窗口过滤 + ├── Step 3: 同源标题去重 + ├── Step 4: SQLite 缓存查询(分离已处理/待处理文章) + ├── Step 5: 外文标题并发翻译(ThreadPoolExecutor × AI_CONCURRENCY) + ├── Step 6: 关键词筛选(仅当 >15篇) + ├── Step 7: 外文正文并发翻译(仅筛选通过的文章,大幅省 token) + ├── Step 8: 批量 AI 评分 + 分类 + 摘要(并发) + ├── Step 9: 新处理文章写入 SQLite 缓存 + ├── Step 10: 合并缓存+新文章,按评分降序 + ├── Step 11: TOP3 网摘生成(优先缓存命中,支持字数重试,TXT+PNG) + ├── Step 12: 四分类整理 + 深度洞察生成(优先缓存命中) + ├── Step 13: Markdown 报告输出(全缓存+文件已存在则跳过) + ├── Step 14: 多渠道推送(企业微信/飞书 webhook,失败优雅降级) + └── 监控报告输出(阶段耗时/API+token统计/源成功率/缓存命中率) +``` + +## ✅ 系统要求 + +- Python 3.8+ 或 Docker +- OpenAI API Key(或兼容API,如火山引擎、DeepSeek等) +- 内存 ≥ 512MB +- 磁盘 ≥ 1GB + +## ❓ 常见问题 + +### 生成的图片中文字体乱码怎么办? +无需额外配置,代码已自动适配所有主流系统的自带中文字体: +- Windows: 自动匹配宋体/黑体/微软雅黑 +- Linux: 自动匹配NotoSansCJK/文泉驿微米黑 +- macOS: 自动匹配PingFang/黑体 + +如果需要完全不依赖系统字体,可以下载开源无版权的NotoSansCJK字体放到`scripts/modules/assets/fonts/`目录下: +- 粗体:`NotoSansCJK-Bold.ttc` +- 常规:`NotoSansCJK-Regular.ttc` + +### 日志输出在哪里? +日志默认输出到标准错误流,包含INFO/WARNING/ERROR三个级别,运行时会实时打印到控制台,也可以重定向到日志文件: +```bash +python scripts/military_daily_report_v3.py >> logs/runtime.log 2>&1 +``` + +--- + +*V3 版本 - 全流程重构 + 模块化拆分 + 跨系统字体适配 + 日志标准化 + Markdown报告输出,2026年5月发布* diff --git a/README.md b/README.md index 5c561b5..a7484df 100644 --- a/README.md +++ b/README.md @@ -1,286 +1,517 @@ -# 🪖 军事科技每日摘要系统 V3 +# 军事科技每日资讯推送系统 -完整的军事科技 RSS 抓取 + AI 智能分析 + 增量缓存 + 运行监控系统 +基于大模型的军事/科技新闻采集、评分、整合与推送系统。自动抓取 RSS 订阅源,经 LLM 评分筛选与实体聚类后,生成日报并推送到飞书群。 -## ✨ 完整功能 +## 系统架构 -### 📥 数据抓取 -- 🔗 可配置 RSS 源直抓(rss_feeds.txt 管理,支持 100+ 源) -- ⏰ 24 小时时间窗口过滤 -- 🔄 同源标题去重(保留跨源对同一事件的不同报道) -- ⚡ ThreadPoolExecutor 并发抓取,内置失败重试 +``` +┌───────────────────────────────────────────────────────────────┐ +│ Fetch 循环(每 30 分钟) │ +│ RSS 抓取 → 中英翻译 → LLM 评分 → 硬约束过滤 → 动态阈值 │ +│ → 实体提取 + 角度分类 → 实体归一化 → 实体聚类 │ +│ → 广告过滤 → 缓存 → 簇热度计算 → 即时推送(≥90 分) │ +└──────────────────┬────────────────────────────────────────────┘ + ↓ +┌───────────────────────────────────────────────────────────────┐ +│ Push 循环(每日 08:00) │ +│ 推送 1: 🔥 热点速览(簇视图) │ +│ 今日速览 + 热点洞察(含[持续跟踪])+ 跨日追踪 + 趋势分析 │ +│ 推送 2: 📰 军事科技每日精选(单篇视图) │ +│ 网摘 Top3 + 分类概览(5 类 × 5 条) │ +│ 推送 3: 🖼️ 网摘图片(PNG 合并长图,图床上传后推送) │ +└───────────────────────────────────────────────────────────────┘ +``` -### 🗄️ 增量缓存 -- 💾 SQLite 本地缓存:文章翻译/AI分析结果持久化 -- 📰 网摘文本缓存:再次运行零 token 消耗 -- 🏷️ 分类介绍缓存:按日期+分类独立存储 -- 🧹 自动过期清理(7天)+ 表结构自动迁移 +| 核心功能 | 说明 | +|---------|------| +| 订阅源管理 | 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 调用统计 + 源抓取成功率 + 缓存命中率 | -### 🌐 智能翻译 -- 🔍 自动识别外文文章 -- 📝 分步翻译:先标题 → 再正文(仅通过筛选的文章) -- ⚡ 并发翻译(ThreadPoolExecutor) +## 快速开始 -### 🔑 关键词筛选 -- 🎯 44 个军事科技专业关键词库 -- 📊 命中数排序,文章 >15 篇时自动过滤 +### 环境要求 -### 🤖 AI 智能分析 -- ⭐ 多维度评分(技术35% + 战略30% + 信息20% + 时效15%) -- 📋 自动分类:今日必看 / 装备动态 / 地区冲突 / 战略政策 -- ✍️ 每篇文章 AI 智能摘要(80-120字) -- 🔮 分类深度洞察分析(每类50字综述) -- 🏆 TOP3 必看深度分析 -- ⚡ 批量并发评分 + 分类 +- Python 3.10+ +- 能访问 OpenAI 兼容 API(DeepSeek / 火山引擎 / OpenAI 等) -### 🖼️ 图片生成 -- 📄 3800px 超长网摘图片 -- 🎨 军事主题视觉设计 -- 📊 包含TOP3完整内容 -- 💾 自动保存PNG文件 - -### 📊 运行监控 -- ⏱ 各阶段耗时统计,自动输出结构化报表 -- 🤖 API 调用量/token 按用途和模型分组统计 -- 📰 源抓取成功/失败率一目了然 -- 📡 文章统计 + 缓存命中率 - -## 🚀 快速开始 - -### 方式一:本地直接运行(推荐) +### 安装 ```bash -# 1. 安装依赖 +# 1. 进入项目目录 +cd my-daily + +# 2. 安装依赖 pip install -r requirements.txt -# 2. 配置环境 -cp config/.env.example config/.env -vim config/.env -# 编辑 OPENAI_API_KEY +# 3. 配置环境变量 +cp .env.example .env +# 编辑 .env,填入 API Key 和 Webhook 地址 -# 3. 运行 -make local +# 4. 配置系统参数(可选,已有默认值) +cp config.json.example config.json +# config.json 已存在时跳过,按需修改调度/评分/源过滤参数 ``` -### 方式二:Docker 部署 +### 环境变量(.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 -# 1. 克隆或解压 -cd military-digest-v3 - -# 2. 配置环境 -cp config/.env.example config/.env -vim config/.env -# 编辑 OPENAI_API_KEY - -# 3. 构建镜像 -make build - -# 4. 测试运行 -make run-once - -# 5. 安装定时任务 -make install-cron +python start.py ``` -## 📁 目录结构 +同时启动数据管线后端(Fetch + Push 循环)和 Web 归档站点(http://0.0.0.0:8080)。所有终端输出实时写入 `logs/YYYYMMDD-HHmmSS.log`,按 Ctrl+C 安全停止所有服务。 -``` -military-digest-v3/ -├── scripts/ -│ ├── military_daily_report_v3.py # 主入口 — 流程编排 -│ └── modules/ # 功能模块包 -│ ├── __init__.py # 包初始化 + 统一导出 -│ ├── config.py # 配置模块:常量 + AI配置加载 -│ ├── utils.py # 工具函数:语言检测/HTML清洗/AI调用/换行 -│ ├── rss_fetcher.py # RSS抓取:12源 × 6线程并发 -│ ├── translator.py # 翻译处理:中英分离 + 并发翻译 -│ ├── keyword_filter.py # 关键词筛选:49词命中排序 -│ │ ├── ai_analyzer.py # AI分析:评分/分类/摘要/洞察/网摘生成 -│ │ ├── cache.py # SQLite缓存:文章/网摘/分类介绍增量缓存 -│ │ ├── monitor.py # 运行监控:阶段耗时/API/AI token调用统计 -│ │ ├── pusher.py # 推送模块:企业微信/飞书 webhook 推送 -│ │ ├── image_generator.py # 图片生成:TOP3合并3800px长图 -│ └── get_chinese_font.py # 字体模块:跨系统中文字体适配 -├── config/ -│ ├── config.json # 系统配置 -│ └── .env.example # 环境变量示例 -├── output/ # 输出目录 -│ ├── military_report_YYYYMMDD.md # 完整报告(Markdown格式,支持链接、样式) -│ ├── military_webzine_YYYYMMDD.txt # TOP3网摘文本 -│ └── military_webzine_YYYYMMDD.png # TOP3网摘合并长图 -├── logs/ # 日志目录 -├── Dockerfile -├── docker-compose.yml -├── Makefile -└── README.md -``` - -## 🧩 模块架构 - -``` -military_daily_report_v3.py ← 主入口(流程编排) - ├── config.py ← 配置常量,零依赖 - ├── logger.py ← 统一日志模块 - ├── cache.py ← SQLite增量缓存,自动迁移 - ├── monitor.py ← 运行监控统计 - ├── pusher.py ← 企业微信/飞书推送 - ├── rss_fetcher.py ← 依赖 config + utils + monitor - ├── translator.py ← 依赖 utils - ├── keyword_filter.py ← 依赖 config - ├── ai_analyzer.py ← 依赖 config + utils - ├── image_generator.py ← 依赖 utils + get_chinese_font - └── get_chinese_font.py ← 零依赖 -``` - -### 各模块职责 - -| 模块 | 行数 | 职责 | 对外导出 | -|------|------|------|----------| -| `config.py` | 90 | RSS源、关键词库、评分维度、分类定义、AI配置加载 | `RSS_FEEDS`, `WECHAT_SOURCES`, `KEYWORDS`, `SCORE_DIMENSIONS`, `CATEGORIES`, `load_ai_config()` | -| `utils.py` | 130+ | 语言检测、HTML清理、时间解析、AI API封装(含监控钩子)、文本换行 | `is_chinese()`, `clean_html()`, `extract_content()`, `parse_pub_time()`, `call_ai()`, `wrap_text()` | -| `rss_fetcher.py` | 100+ | 多线程并行抓取RSS源(MAX_THREADS并发,含2次重试+监控上报) | `fetch_all_feeds()` | -| `translator.py` | 150+ | 中英文分离 + 标题/正文分步AI并发翻译 | `batch_translate_titles()`, `batch_translate_contents()` | -| `keyword_filter.py` | 23 | 44关键词命中计数 → 排序 → Top15筛选 | `keyword_filter()` | -| `ai_analyzer.py` | 240+ | 四维度评分、智能分类、中文摘要、分类洞察、《参考消息》风格网摘生成 | `score_and_classify_article()`, `calculate_weighted_score()`, `generate_category_overview()`, `generate_webzine_for_article()`, `batch_score_and_classify_articles()` | -| `cache.py` | 310+ | SQLite增量缓存:文章处理结果+网摘+分类介绍,支持自动迁移+过期清理+断点续跑 | `get_cache()`, `get_article()`, `save_article()`, `save_article_webzine()`, `get_category_summary()`, `save_category_summary()` | -| `monitor.py` | 160+ | 运行时监控:阶段耗时/AI API调用量+token/源成功率/缓存命中率,结束自动输出报表 | `get_monitor()`, `monitor.stage()`, `monitor.report()` | -| `pusher.py` | 130+ | 企业微信文本/图片/Markdown推送 + 飞书文本推送,主流程末自动触发,失败优雅降级 | `send_daily_push()`, `push_wechat_text()`, `push_wechat_image()`, `push_feishu_text()` | -| `image_generator.py` | 220 | 网摘文本渲染为PNG图片(单篇 + TOP3合并长图) | `create_webzine_image()`, `create_combined_webzine_image()` | -| `get_chinese_font.py` | 50 | 跨系统中文字体自动匹配,支持Windows/Linux/macOS,内置开源字体可选 | `get_chinese_font(size, bold)` | - -## ⚙️ 配置说明 - -### 环境变量 (.env) - -| 配置项 | 说明 | 默认值 | -|--------|------|--------| -| OPENAI_API_KEY | OpenAI API 密钥 | - | -| OPENAI_API_BASE | API 地址 | https://api.openai.com/v1 | -| OPENAI_MODEL | AI 分析模型 | gpt-4o-mini | -| WEBZINE_MODEL | 网摘专用模型 | deepseek-v3.2-250518 | - -### config.json 配置项 - -| 配置项 | 说明 | 默认值 | -|--------|------|--------| -| time_window_hours | 时间窗口(小时) | 12 | -| max_articles | 最多保留文章数 | 15 | -| top3_count | TOP3 必看文章数 | 3 | -| wechat_target | 微信接收者ID | - | -| wechat_account | 微信机器人账号 | - | -| enable_wechat_push | 开启微信推送 | true | -| enable_feishu_push | 开启飞书推送 | false | -| enable_image_gen | 开启图片生成 | true | -| enable_txt_gen | 开启TXT文件生成 | true | - -### rss_feeds.txt 订阅源配置 -所有RSS源都在`config/rss_feeds.txt`文件中管理,不需要修改代码即可增删订阅源: -- 格式:每行 `源名称|RSS地址` -- 以`#`开头的行是注释,会自动忽略 -- 空行会自动跳过 -- 修改后直接运行程序,无需重启或改代码 -- ✅ 容错保障:文件不存在、为空或格式错误时,自动回退使用内置的12个默认源,不会影响程序运行 -- 支持所有标准RSS/Atom格式,中英文源无需区分,系统自动识别翻译 - -## ⏰ 定时任务 - -### 方式一:宿主机 crontab +### main.py 命令 ```bash -make install-cron -# 或手动添加 -crontab -e -# 加入:0 8 * * * cd /path/to/military-digest-v3 && python3 scripts/military_daily_report_v3.py >> logs/cron.log 2>&1 +python main.py [options] ``` -### 方式二:Docker Cron +| 命令 | 说明 | 示例 | +|------|------|------| +| `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 -docker-compose --profile cron up -d +sudo bash scripts/setup_systemd.sh # 一键安装 +bash scripts/status.sh # 查看运行状态 +sudo journalctl -u my-daily-fetch -f # 实时日志 +sudo bash scripts/uninstall_systemd.sh # 卸载 ``` -## 🔍 RSS 源列表 +### Windows(计划任务) -1. Defense One - 美国防务新闻 -2. NEWUAS - 无人机系统新闻 -3. Seapower - 海军力量杂志 -4. The War Zone - 战区军事分析 -5. 国防科技要闻 -6. 战略前沿技术 -7. 无人机邦 -8. 浮空飞行器 -9. 海鹰资讯 -10. 渊亭防务 -11. 电波之矛 -12. 龙牙的一座山 - -## 📊 输出示例 - -``` -🪖 军事科技每日摘要 -📅 2026年05月12日 | 共收录 12 篇 - -==================== -🔥 今日必看 TOP3 -==================== - -1.【美军MQ-9无人机测试发射激光制导火箭弹】 - ⭐ 综合评分:9.2/10 - 📰 来源:The War Zone - 📝 摘要:美国通用原子公司联合美空军在内华达测试场完成... - 🔮 深度洞察:低成本改装令察打无人机获得反无人机能力... - 🔗 阅读原文:... - -... +```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 主机) -``` -main() - ├── Step 1: RSS 并行抓取(ThreadPoolExecutor × MAX_THREADS 并发,内置重试) - ├── Step 2: 24小时时间窗口过滤 - ├── Step 3: 同源标题去重 - ├── Step 4: SQLite 缓存查询(分离已处理/待处理文章) - ├── Step 5: 外文标题并发翻译(ThreadPoolExecutor × AI_CONCURRENCY) - ├── Step 6: 关键词筛选(仅当 >15篇) - ├── Step 7: 外文正文并发翻译(仅筛选通过的文章,大幅省 token) - ├── Step 8: 批量 AI 评分 + 分类 + 摘要(并发) - ├── Step 9: 新处理文章写入 SQLite 缓存 - ├── Step 10: 合并缓存+新文章,按评分降序 - ├── Step 11: TOP3 网摘生成(优先缓存命中,支持字数重试,TXT+PNG) - ├── Step 12: 四分类整理 + 深度洞察生成(优先缓存命中) - ├── Step 13: Markdown 报告输出(全缓存+文件已存在则跳过) - ├── Step 14: 多渠道推送(企业微信/飞书 webhook,失败优雅降级) - └── 监控报告输出(阶段耗时/API+token统计/源成功率/缓存命中率) -``` - -## ✅ 系统要求 - -- Python 3.8+ 或 Docker -- OpenAI API Key(或兼容API,如火山引擎、DeepSeek等) -- 内存 ≥ 512MB -- 磁盘 ≥ 1GB - -## ❓ 常见问题 - -### 生成的图片中文字体乱码怎么办? -无需额外配置,代码已自动适配所有主流系统的自带中文字体: -- Windows: 自动匹配宋体/黑体/微软雅黑 -- Linux: 自动匹配NotoSansCJK/文泉驿微米黑 -- macOS: 自动匹配PingFang/黑体 - -如果需要完全不依赖系统字体,可以下载开源无版权的NotoSansCJK字体放到`scripts/modules/assets/fonts/`目录下: -- 粗体:`NotoSansCJK-Bold.ttc` -- 常规:`NotoSansCJK-Regular.ttc` - -### 日志输出在哪里? -日志默认输出到标准错误流,包含INFO/WARNING/ERROR三个级别,运行时会实时打印到控制台,也可以重定向到日志文件: ```bash -python scripts/military_daily_report_v3.py >> logs/runtime.log 2>&1 +# 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 ≥ 阈值` 的文章进入下一步实体提取。 + --- -*V3 版本 - 全流程重构 + 模块化拆分 + 跨系统字体适配 + 日志标准化 + Markdown报告输出,2026年5月发布* +### 第二层:簇级评价 + +#### 步骤 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 以内。 \ No newline at end of file