v1.1.0: 真实网页采集(可读正文全文入库) + 大模型接口多预置一键切换(SiliconFlow默认) + 数据源可编辑
- 新增 crawler.py: requests+bs4 readability风格清洗, 提取候选链接按文章相似度排序, 前5条抓全文存 articles.full_text, 详情页展示; example.com占位源走模拟, 真实源失败标记error不造假 - 大模型: 新增 llm_providers 表(预置 SiliconFlow/DeepSeek官方/Autodl/Local Qwen), 设置页增删改/测试/一键切换, 激活接口失败自动切换备用 - 数据源: 前端补编辑按钮+弹窗(后端 update 已支持), 列表显示URL与采集状态 - 数据库迁移: articles.full_text 列 + llm_providers 表
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
一款面向 AI 领域的**自动采集 → 智能分析 → 邮件推送**的新闻跟踪系统。后台定时从数据源采集资讯,先规则打分、再 LLM 深度分析,把与你兴趣画像相关且重要的资讯**实时发邮件提醒**,并每天 10:00 发一份**AI 资讯日报**。带完整网页管理台,兴趣画像/数据源/通知参数全部可配。
|
||||
|
||||
> 当前版本 v1.0.1(补充说明文档);当前数据源为**高仿真模拟数据**(simulate.py),全链路已跑通,接入真实源只需在 sources 适配层实现 `fetch()`。
|
||||
> 当前版本 **v1.1.0**:真实网页采集(可读正文入库)+ 大模型接口多预置一键切换 + 数据源可编辑。
|
||||
|
||||
---
|
||||
|
||||
@@ -14,16 +14,20 @@
|
||||
│ sources │───▶│ scheduler │───▶│ analysis.py │───▶│ notifier.py │
|
||||
│ (7个默认) │ │ (后台线程) │ │ (规则+LLM两级分析) │ │ (实时+日报) │
|
||||
└──────────┘ └──────────────┘ └──────────────────┘ └─────────────────┘
|
||||
模拟源 fetch() 每30分钟采集一次 规则打分→候选 LLM完成→重要度判定
|
||||
simulate.py (scan_interval_min) →后台LLM深度分析 →发实时邮件
|
||||
每天10:00日报 →实时/日报邮件
|
||||
真实URL→爬虫抓取 每30分钟采集一次 规则打分→候选 LLM完成→重要度判定
|
||||
crawler.py (scan_interval_min) →后台LLM深度分析 →发实时邮件
|
||||
正文清洗+全文入库 每天10:00日报 →实时/日报邮件
|
||||
example.com→模拟 大模型可一键切换
|
||||
```
|
||||
|
||||
**完整链路:**
|
||||
|
||||
1. **采集**(每 `scan_interval_min` 分钟,默认 30):`scheduler.collect_once()` 调 `simulate.fetch_simulated()` 拉取新资讯 → 按 URL 去重 → 入库 `articles` 表。
|
||||
1. **采集**(每 `scan_interval_min` 分钟,默认 30):`scheduler.collect_once()` 调 `crawler.fetch_all()`——
|
||||
- 真实 URL 源:用 `requests` 抓页面 → **清洗出干净可读正文**(readability 风格,去除导航/广告/脚本)→ 提取候选资讯链接(按文章相似度排序、过滤导航词)→ 对前 5 条抓全文,**连同页面可读正文一起入库**(`articles.full_text`,详情页可查看);
|
||||
- `example.com` 占位源:用 `simulate.items_for_source()` 仿真数据填充,保证链路不空;
|
||||
- 真实源抓取失败:跳过并标记该源 `status=error`(数据源页可见),**不塞模拟数据冒充**。
|
||||
2. **规则打分**(立即):`analysis.analyze_article()` 对每条新资讯算**兴趣相关度**(关键词命中权重 + 领域匹配 + 关注公司命中)和**重要度启发式**(发布/融资/禁令等强信号词、金额量级、时效性、数据源权重、公司影响),得到**综合分 total_score (0-100)**。
|
||||
3. **LLM 深度分析**(后台异步):规则分 ≥ `llm_threshold`(默认 60)的资讯进入 `llm_analyze()`,调用 DeepSeek 输出重要度 1-10、相关度、分类、一句话结论,并与规则分融合更新。
|
||||
3. **LLM 深度分析**(后台异步):规则分 ≥ `llm_threshold`(默认 60)的资讯进入 `llm_analyze()`,**使用网页激活的大模型接口**(默认 SiliconFlow,可一键切换;调用失败自动切换下一个可用接口),输出重要度 1-10、相关度、分类、一句话结论,并与规则分融合更新。
|
||||
4. **实时通知**:扫描「重要 + 已分析完成 + 未通知」的资讯,综合分 ≥ `realtime_threshold`(默认 80)→ 发 **🔥 重要AI资讯实时提醒** 邮件,标记 `notified=1`。
|
||||
5. **每日日报**(默认每天 10:00):汇总往前 `summary_window_hours`(默认 24h)内综合分 ≥50 的资讯,按分排序取前 `max_summary_items`(默认 15)条发 **📰 AI资讯日报**,含领域分布统计。
|
||||
|
||||
@@ -31,13 +35,14 @@
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 📥 **自动定时采集**:数据源可增删改、可启停,每源带权重(影响重要度打分)
|
||||
- 🧠 **两级智能分析**:规则打分秒级响应 + DeepSeek LLM 深度分析(重要度/相关度/分类/结论)
|
||||
- 📥 **真实网页采集**:真实 URL 源自动抓取 → readability 风格清洗出干净可读正文 → **全文入库**(详情页可看),提取候选资讯链接按文章相似度排序;`example.com` 占位源走仿真数据;失败源标记 error 不造假
|
||||
- 🧠 **两级智能分析**:规则打分秒级响应 + LLM 深度分析(重要度/相关度/分类/结论)
|
||||
- 🤖 **大模型接口可配置**:设置页可增删改/测试大模型接口,预置 SiliconFlow(默认)/ DeepSeek 官方 / Autodl / Local Qwen 四个,**一键切换即时生效**,激活接口失败自动切换下一个可用接口
|
||||
- 🔥 **实时重要资讯邮件**:综合分达到阈值自动推送,单批最多 10 条
|
||||
- 📰 **每日 AI 资讯日报**:默认每天 10:00,按领域统计 + 重点资讯卡片
|
||||
- 🎯 **兴趣画像管理**:关键词(带权重)、领域、关注公司,全部可在网页维护,改完一键「重新打分」
|
||||
- 🔗 **数据源管理**:7 个内置数据源模板,启停/权重/类型自由配置
|
||||
- 📊 **网页管理台**:仪表盘(总数/重要/待分析/趋势/领域分布)、资讯列表(筛选/搜索/分页)、详情页、通知日志
|
||||
- 🔗 **数据源管理**:7 个内置数据源模板,**可编辑**(名称/类型/URL/权重/描述)、启停、删除,每源带权重
|
||||
- 📊 **网页管理台**:仪表盘(总数/重要/待分析/趋势/领域分布)、资讯列表(筛选/搜索/分页)、详情页(含全文)、通知日志
|
||||
- 📧 **邮件通知**:支持 plain / starttls / ssl 三种 SMTP 模式,可测试发送
|
||||
- 🛠 **手动操作台**:一键采集 / 一键 LLM 分析 / 一键发日报 / 一键造数据 / 重新打分 / 测试邮件
|
||||
|
||||
@@ -46,8 +51,9 @@
|
||||
## 技术栈
|
||||
|
||||
- **后端**:Python 3 + Flask(threaded)
|
||||
- **网页采集**:requests + BeautifulSoup/lxml(readability 风格正文清洗)
|
||||
- **数据库**:SQLite(原生 sqlite3,WAL 模式,无 ORM)
|
||||
- **大模型**:DeepSeek `deepseek-v4-flash`(OpenAI 兼容接口,`response_format=json_object`)
|
||||
- **大模型**:OpenAI 兼容接口,默认 SiliconFlow `deepseek-ai/DeepSeek-V4-Flash`(可一键切换,`response_format=json_object`)
|
||||
- **前端**:原生 HTML/CSS/JS + Jinja2 模板(无前端框架)
|
||||
|
||||
---
|
||||
@@ -56,12 +62,13 @@
|
||||
|
||||
```
|
||||
news-tracker/
|
||||
├── app.py # Flask 主应用:页面路由 + API
|
||||
├── config.py # 全局配置(端口/LLM/邮件/自动化默认值/默认画像/数据源模板)
|
||||
├── db.py # SQLite 数据访问层(原生 sqlite3)
|
||||
├── app.py # Flask 主应用:页面路由 + API(含 /api/llm 大模型接口管理)
|
||||
├── config.py # 全局配置(端口/LLM/预置大模型接口/采集参数/自动化/画像/数据源模板)
|
||||
├── db.py # SQLite 数据访问层(原生 sqlite3;含 llm_providers / full_text 迁移)
|
||||
├── crawler.py # 真实网页采集:抓取 + readability 清洗 + 链接提取 + 全文入库
|
||||
├── scheduler.py # 后台调度器:定时采集 + 每日日报 + 实时通知扫描
|
||||
├── analysis.py # 智能分析引擎:规则打分 + LLM 深度分析
|
||||
├── simulate.py # 模拟数据源(真实源接入前跑通全链路)
|
||||
├── analysis.py # 智能分析引擎:规则打分 + LLM 深度分析(多接口自动切换)
|
||||
├── simulate.py # 模拟数据源(example.com 占位源 / 真实源失败时回退)
|
||||
├── notifier.py # 邮件通知(实时 / 日报,plain/starttls/ssl)
|
||||
├── start.sh # 启动/停止/状态脚本
|
||||
├── templates/ # Jinja2 页面模板
|
||||
@@ -111,9 +118,22 @@ cd works/news-tracker
|
||||
|
||||
`smtp_host` / `smtp_port` / `smtp_user` / `smtp_pass` / `smtp_mode`(plain|starttls|ssl) / `email_to` / `sender_name`。默认 `mail.tphai.com:587` plain,收件人 `wlq@tphai.com`。
|
||||
|
||||
### 大模型配置(改 config.py)
|
||||
### 大模型接口(设置页,一键切换)
|
||||
|
||||
`LLM_BASE_URL` / `LLM_API_KEY` / `LLM_MODEL` / `LLM_TIMEOUT` / `LLM_MAX_TOKENS` / `LLM_TEMPERATURE`。
|
||||
预置 4 个接口(`config.py` 的 `LLM_PROVIDERS_DEFAULT`,首启写入 `llm_providers` 表):
|
||||
|
||||
| 名称 | Base URL | 模型 |
|
||||
|------|----------|------|
|
||||
| **SiliconFlow(默认激活)** | `https://api.siliconflow.cn/v1` | `deepseek-ai/DeepSeek-V4-Flash` |
|
||||
| DeepSeek 官方 | `https://api.deepseek.com` | `deepseek-v4-flash` |
|
||||
| Autodl(火山方舟中转) | `https://www.autodl.art/api/v1` | `qwen3.6-plus` |
|
||||
| Local Qwen(内网) | `http://121.40.164.32:18003/v1` | `unsloth/Qwen3.8-27B-Q6_K` |
|
||||
|
||||
设置页可**增删改/测试**任意接口,点「⚡ 切换为当前」一键切换即时生效;分析时当前接口失败会自动切换下一个可用接口。`config.py` 里的 `LLM_BASE_URL/KEY/MODEL` 仅作无激活记录时的回退。
|
||||
|
||||
### 采集参数(config.py)
|
||||
|
||||
`CRAWL_DEFAULTS`:`per_source_links`(每源最多采集条目,默认 8)、`full_fetch_links`(其中抓全文条数,默认 5)、`crawl_timeout`(单页超时,默认 20s)、`user_agent`。
|
||||
|
||||
---
|
||||
|
||||
@@ -123,11 +143,11 @@ cd works/news-tracker
|
||||
|------|------|
|
||||
| `/dashboard` | 仪表盘:总资讯/重要资讯/待分析/已通知 + 近7天趋势 + 领域分布 |
|
||||
| `/news` | 资讯列表:按领域/重要/关键词搜索,分页 |
|
||||
| `/news/<id>` | 资讯详情:规则分/LLM分/实体/分析结论 |
|
||||
| `/sources` | 数据源管理:增删改、启停、权重 |
|
||||
| `/news/<id>` | 资讯详情:规则分/LLM分/实体/分析结论 + **页面可读全文** |
|
||||
| `/sources` | 数据源管理:**编辑**/启停/删除/权重,真实源状态可见 |
|
||||
| `/profile` | 兴趣画像:关键词/领域/公司维护 |
|
||||
| `/logs` | 通知日志(实时/日报发送记录) |
|
||||
| `/settings` | 设置:自动化参数 + 邮件配置 + 测试 |
|
||||
| `/settings` | 设置:自动化参数 + 邮件配置 + **大模型接口管理(一键切换/测试)** |
|
||||
|
||||
---
|
||||
|
||||
@@ -139,6 +159,7 @@ cd works/news-tracker
|
||||
| `/api/sources` | POST | `action=add\|update\|delete\|toggle` 数据源管理 |
|
||||
| `/api/profile` | POST | `action=add\|delete`,`kind=keyword\|domain\|company` 画像维护 |
|
||||
| `/api/settings` | POST | 更新 `auto` / `mail` 设置 |
|
||||
| `/api/llm` | POST | 大模型接口:`add\|update\|delete\|switch\|toggle\|test`(switch=一键切换) |
|
||||
| `/api/actions` | POST | `action=collect`(采集) `llm`(LLM分析) `summary`(发日报) `seed`(造数据) `reanalyze`(重新打分) `test_mail`(测试邮件) |
|
||||
|
||||
请求体为 JSON,如:`{"action": "collect"}`、`{"action": "llm", "limit": 10}`。
|
||||
@@ -147,9 +168,10 @@ cd works/news-tracker
|
||||
|
||||
## 数据模型
|
||||
|
||||
- **sources**:数据源(name/type/url/weight/enabled/status/last_fetch/last_count)
|
||||
- **articles**:资讯(title/url/content/summary/domain/entities/importance/relevance/total_score/is_important/analysis/llm_status/notified/status/published_at/collected_at)
|
||||
- **sources**:数据源(name/type/url/weight/enabled/status/last_fetch/last_count;status 标记真实源采集 ok/error)
|
||||
- **articles**:资讯(title/url/content/summary/**full_text(页面可读全文)**/domain/entities/importance/relevance/total_score/is_important/analysis/llm_status/notified/status/published_at/collected_at)
|
||||
- **keywords** / **domains** / **companies**:兴趣画像
|
||||
- **llm_providers**:大模型接口(name/base_url/api_key/model/active/enabled;active=当前激活)
|
||||
- **notification_log**:邮件通知日志
|
||||
- **settings**:KV 配置(`auto` / `mail` 为 JSON)
|
||||
|
||||
@@ -161,30 +183,22 @@ cd works/news-tracker
|
||||
|
||||
## 接入真实数据源
|
||||
|
||||
当前用 `simulate.py` 模拟采集跑通全链路。接入真实源只需:
|
||||
系统已内置真实网页采集(`crawler.py`),接入真实源**无需写代码**:
|
||||
|
||||
1. 新建 `sources_xxx.py`,实现 `fetch() -> list[dict]`,返回结构与模拟源一致:
|
||||
```python
|
||||
# 每条 dict 至少含:
|
||||
# title, url, content(或summary), published_at(YYYY-MM-DD HH:MM:SS), domain, entities(list)
|
||||
```
|
||||
2. 在 `scheduler.collect_once()` 里把 `simulate.fetch_simulated()` 换成真实 `fetch()`(可多源合并)。
|
||||
3. 其余逻辑(去重/打分/LLM/通知/网页)**无需改动**。
|
||||
1. 在数据源页「编辑」已有源或「新增」源,填真实 URL(如媒体频道/官网新闻/RSS 页);
|
||||
2. 保存后下次采集会自动抓取该页 → 清洗出可读正文 → 提取资讯链接 → 对前 5 条抓全文入库;
|
||||
3. 抓取失败的源会在数据源页标记 **error** 状态(网络被拒/反爬),不阻塞其他源;
|
||||
4. `example.com` 开头的占位地址继续走模拟数据,方便调试。
|
||||
|
||||
---
|
||||
|
||||
## 当前状态
|
||||
|
||||
- ✅ 服务运行中:端口 **16100**
|
||||
- ✅ 数据库已有 **32 条**资讯(重要 12 条,LLM 已分析 12 条,已通知 12 条)
|
||||
- ✅ 邮件链路已验证(`mail.tphai.com:587` plain,收件人 `wlq@tphai.com`)
|
||||
- 🕐 数据源为模拟数据,等待接入真实源
|
||||
> 提示:部分站点(Next.js 重 JS 渲染 / 强反爬)服务端 HTML 拿不到正文,会提取不到链接(count=0);本机对 arXiv/GitHub/OpenAI 等站网络不稳定,建议优先添加可达的站点。
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
- **收不到邮件?** 在设置页点「测试邮件」;确认 `smtp_mode` 与端口匹配(plain 一般不加密、starttls 用 587、ssl 用 465)。
|
||||
- **LLM 分析失败?** 设置页大模型接口点「测试」;切一个更稳的接口(如 SiliconFlow);系统会自动切备用接口,仍失败则该条标 `error` 不阻塞。
|
||||
- **真实源采集不到?** 数据源页看该源状态是否 **error**(网络被拒/反爬);可换成可达的站点或 RSS 地址。
|
||||
- **想立即看效果?** 数据管理页(`/api/actions` 手动)点「立即采集 / LLM 分析 / 发送日报」。
|
||||
- **改了兴趣画像想重新算分?** 点「重新打分」(reanalyze)即可全量重跑规则打分。
|
||||
- **日志在哪?** `logs/app.log`(服务日志)+ 网页 `/logs`(通知日志)。
|
||||
@@ -194,4 +208,4 @@ cd works/news-tracker
|
||||
## Git
|
||||
|
||||
- 仓库:`hz4th_coder/news-tracker`
|
||||
- 版本:`v1.0.0`(初版)→ `v1.0.1`(补 README)
|
||||
- 版本:`v1.0.0`(初版)→ `v1.0.1`(补 README)→ **`v1.1.0`**(真实网页采集+全文入库 / 大模型接口多预置一键切换 / 数据源可编辑)
|
||||
Reference in New Issue
Block a user