# 医药新闻聚合系统 — 设计方案 > 版本:v1.0 | 日期:2026-05-24 --- ## 一、项目目标 每日自动抓取全网中英文医药新闻(约 100 条),经 AI 深度加工后精选 10 条,以网页形式展示,未来对接微信小程序。 --- ## 二、整体架构 ``` ┌─────────────────────────────────────────────────────┐ │ 定时调度器 │ │ APScheduler (每日 06:00) │ └───────────────────────┬─────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 抓取层 Crawler │ │ RSS Fetcher │ HTTP Scraper │ NewsAPI Client │ │ (中文源) │ (备用) │ (英文源) │ └───────────────────────┬─────────────────────────────┘ ↓ 原始新闻 (~100条/天) ┌─────────────────────────────────────────────────────┐ │ 数据库 PostgreSQL │ │ raw_news │ processed_news │ llm_config │ │ │ news_sources │ system_logs │ └───────────────────────┬─────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ AI 处理流水线 │ │ 1. 相关性过滤(去除非医药内容) │ │ 2. 去重(相似度检测) │ │ 3. 摘要生成(中文,150字) │ │ 4. 观点提炼(核心结论/影响) │ │ 5. 关键词提取(5-8个标签) │ │ 6. 重要性评级(1-10分 + 理由) │ │ 7. 分类标注(4个类别) │ │ 8. 精选 TOP 10 │ └───────────────────────┬─────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ FastAPI 后端 │ │ 读者 API │ 管理员 API │ │ GET /news │ POST /admin/llm-config │ │ GET /news/{id} │ GET /admin/sources │ │ GET /news/featured │ POST /admin/trigger-crawl │ └───────────────────────┬─────────────────────────────┘ ↓ ┌───────────────┴───────────────┐ ↓ ↓ ┌──────────────┐ ┌──────────────────┐ │ Vue 3 前端 │ │ 未来:微信小程序 │ │ 读者页 + 管理 │ │ (复用同一 API) │ └──────────────┘ └──────────────────┘ ``` --- ## 三、技术栈 | 层级 | 技术 | 版本 | 说明 | |------|------|------|------| | 任务调度 | APScheduler | 3.x | 每日定时触发,支持手动触发 | | 爬虫 | httpx + BeautifulSoup4 | — | 异步 HTTP,HTML 解析 | | RSS 解析 | feedparser | — | 解析 RSS/Atom 订阅源 | | AI 调用 | 统一适配层(见下) | — | 支持多 LLM 提供商切换 | | 后端框架 | FastAPI | 0.11x | 异步,自动生成 OpenAPI 文档 | | 数据库 | PostgreSQL 16 | — | 主存储,支持全文搜索 | | ORM | SQLAlchemy 2 + Alembic | — | 数据模型 + 迁移 | | 前端框架 | Vue 3 + Vite | — | 组合式 API | | UI 组件库 | Element Plus | — | 中文生态好,适配小程序迁移 | | 部署 | Docker Compose | — | 容器化,国内服务器一键启动 | --- ## 四、LLM 适配层设计 > 国内服务器无法直连 Claude API,需要支持可切换的 LLM 提供商。 ```python # 统一接口,后端只调用这一层 class LLMClient: provider: str # "openai" | "anthropic" | "qwen" | "deepseek" | "custom" api_key: str base_url: str # 支持自定义 endpoint(代理/国内镜像) model: str async def complete(self, messages: list, response_format="json") -> str: # 内部适配不同 provider 的 SDK/HTTP 接口 ... ``` **支持的 LLM 提供商(管理页可配置):** | 提供商 | 说明 | 推荐模型 | |--------|------|----------| | DeepSeek | 国内可直连,性价比高 | deepseek-chat | | 通义千问 (Qwen) | 阿里云,国内服务器友好 | qwen-plus | | OpenAI 兼容 | 走代理或第三方中转 | gpt-4o-mini | | Anthropic Claude | 走代理 | claude-sonnet-4-6 | | 自定义 Endpoint | 私有部署模型 | 自填 | --- ## 五、数据库模型 ```sql -- 新闻来源配置 news_sources ( id, name, url, type ENUM('rss','scrape'), language ENUM('zh','en'), category, is_active, created_at, updated_at ) -- 原始抓取数据 raw_news ( id, source_id, title, url, raw_content, published_at, crawled_at, status ENUM('pending','processed','skipped','error') ) -- AI 处理后数据 processed_news ( id, raw_news_id, title_zh, -- 中文标题(英文原文翻译或原标题) summary, -- 中文摘要(150字) opinion, -- 核心观点/影响(100字) keywords TEXT[], -- 关键词数组 importance_score, -- 重要性 1-10 importance_reason, -- 评分理由 category ENUM('药品监管','临床研究','行业动态','政策法规'), is_featured BOOL, -- 是否入选当日 TOP 10 featured_rank, -- TOP 10 排名 processed_at ) -- LLM 配置(管理页维护) llm_config ( id, name, provider, api_key, base_url, model_name, is_active, created_at ) -- 系统运行日志 system_logs ( id, event_type, message, details JSONB, created_at ) ``` --- ## 六、AI 处理 Prompt 设计 每条新闻用一次 LLM 调用,返回结构化 JSON: ``` 你是医药行业资深分析师。请分析以下新闻,返回 JSON 格式结果。 新闻标题:{title} 新闻内容:{content} 新闻语言:{zh|en} 请返回: { "is_medical_related": true/false, // 是否与医药相关 "title_zh": "中文标题", "summary": "中文摘要(100-150字)", "opinion": "核心观点或行业影响(50-100字)", "keywords": ["关键词1", ..., "关键词5"], "importance_score": 1-10, "importance_reason": "评分理由(30字内)", "category": "药品监管|临床研究|行业动态|政策法规" } 评分标准: 9-10: 重大政策/突破性研究/重要监管决定 7-8: 行业重要动态,影响范围广 5-6: 常规行业新闻,有一定参考价值 1-4: 普通资讯,信息价值有限 ``` **TOP 10 精选策略:** 1. 过滤掉 `is_medical_related = false` 2. 按 `importance_score` 降序排列 3. 每个 category 至少保留 1 条(保证多样性) 4. 最终取前 10 条 --- ## 七、新闻数据来源(初始列表) ### 中文 RSS 源 | 来源 | URL | 类别 | |------|-----|------| | 国家药监局 | https://www.nmpa.gov.cn/rss | 药品监管 | | 丁香园 | https://www.dxy.cn/rss | 临床研究 | | 医学界 | https://www.yxj.org.cn/rss | 行业动态 | | 健康时报 | http://www.jksb.com.cn/rss | 行业动态 | ### 英文 RSS 源 | 来源 | URL | 类别 | |------|-----|------| | STAT News | https://www.statnews.com/feed | 临床研究 | | FiercePharma | https://www.fiercepharma.com/rss/xml | 行业动态 | | FDA News | https://www.fda.gov/about-fda/contact-fda/stay-informed/rss-feeds/fda-news-feed/rss.xml | 药品监管 | | PubMed (医药) | https://pubmed.ncbi.nlm.nih.gov/rss/... | 临床研究 | > 注:以上 URL 需在开发时验证可用性,部分需要爬虫替代 RSS。 --- ## 八、目录结构 ``` ai_news_v1/ ├── backend/ │ ├── app/ │ │ ├── main.py # FastAPI 入口 │ │ ├── config.py # 环境变量配置 │ │ ├── database.py # DB 连接 │ │ ├── models/ │ │ │ ├── news.py │ │ │ ├── source.py │ │ │ └── llm_config.py │ │ ├── api/ │ │ │ ├── news.py # 读者 API │ │ │ └── admin.py # 管理 API │ │ ├── crawler/ │ │ │ ├── rss_fetcher.py # RSS 抓取 │ │ │ └── http_fetcher.py # HTTP 爬取(备用) │ │ ├── ai/ │ │ │ ├── llm_client.py # 统一 LLM 适配层 │ │ │ ├── processor.py # AI 处理流水线 │ │ │ └── selector.py # TOP 10 精选逻辑 │ │ └── scheduler.py # APScheduler 定时任务 │ ├── alembic/ # 数据库迁移 │ ├── requirements.txt │ └── Dockerfile ├── frontend/ │ ├── src/ │ │ ├── views/ │ │ │ ├── NewsReader.vue # 读者主页 │ │ │ ├── NewsDetail.vue # 新闻详情 │ │ │ └── Admin.vue # 管理后台 │ │ ├── components/ │ │ │ ├── NewsCard.vue │ │ │ └── FeaturedBadge.vue │ │ └── api/ │ │ └── index.ts # API 调用封装 │ ├── package.json │ └── Dockerfile ├── docker-compose.yml ├── docker-compose.prod.yml ├── .env.example └── DESIGN.md # 本文档 ``` --- ## 九、API 接口设计 ### 读者端 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/news/featured` | 当日精选 TOP 10 | | GET | `/api/news?date=&category=&page=` | 新闻列表(分页) | | GET | `/api/news/{id}` | 新闻详情 | | GET | `/api/news/dates` | 有数据的日期列表 | ### 管理端(需 Bearer Token 鉴权) | 方法 | 路径 | 说明 | |------|------|------| | GET/POST | `/api/admin/llm-config` | 查看/更新 LLM 配置 | | GET | `/api/admin/sources` | 新闻源列表 | | POST | `/api/admin/sources` | 添加新闻源 | | PUT | `/api/admin/sources/{id}` | 启用/禁用新闻源 | | POST | `/api/admin/crawl/trigger` | 手动触发抓取 | | GET | `/api/admin/logs` | 查看运行日志 | | GET | `/api/admin/stats` | 今日抓取统计 | --- ## 十、前端页面设计 ### 读者主页 - 顶部:Logo + 今日日期 + 上次更新时间 - 主区:精选 TOP 10 卡片列表,每张卡片含: - 重要性评分角标(红/橙/蓝) - 中文标题 - AI 摘要(折叠展开) - 核心观点 - 关键词标签 - 来源 + 原文链接 - 侧边栏(或 Tab):按分类筛选、历史日期切换 ### 管理后台 - LLM 配置面板:provider 选择、API Key、Base URL、模型名、连接测试按钮 - 新闻源管理:表格 + 启用/禁用开关 + 添加 - 手动触发:一键触发今日抓取 + 进度显示 - 运行日志:最近 100 条日志,带时间戳和级别 --- ## 十一、部署方案 ```yaml # docker-compose.yml 核心服务 services: db: # PostgreSQL backend: # FastAPI frontend: # Vue (Nginx 静态托管) scheduler: # APScheduler (可合并入 backend) ``` **国内服务器注意事项:** - LLM API 如需访问境外服务,在服务器配置出口代理,或选用 DeepSeek/Qwen 等国内可直连的模型 - pip/npm 镜像切换为阿里云/清华源 --- ## 十二、开发阶段划分 | 阶段 | 内容 | 预估工作量 | |------|------|-----------| | Phase 1 | DB 模型 + FastAPI 骨架 + LLM 适配层 | 2天 | | Phase 2 | RSS 抓取 + AI 处理流水线 + 定时任务 | 3天 | | Phase 3 | 读者前端(主页 + 详情) | 2天 | | Phase 4 | 管理后台前端 | 2天 | | Phase 5 | Docker 部署 + 联调测试 | 1天 | | 合计 | | **约 10 个工作日** |