Python+Flask+Vue3构建AI新闻聚合系统实战
1. 项目背景:当AI新闻成为信息过载的负担
去年三月,我发现自己每天要花近两小时在20多个AI技术网站间来回切换——OpenAI博客要追更新、arXiv得筛论文、Hacker News看行业动态,还有各种技术论坛和自媒体账号。这种碎片化的信息获取方式不仅效率低下,关键信息还经常被淹没在海量内容中。
作为全栈开发者,我决定用技术手段解决这个痛点。用Python+Flask构建后端API服务,Vue3开发前端界面,配合爬虫和NLP技术,最终打造出能自动聚合、分类和摘要AI领域新闻的个性化站点。现在每天只需花10分钟浏览,就能掌握行业核心动态,实测节省了82%的信息获取时间。
2. 技术架构设计
2.1 整体技术栈选型
- 后端框架:Flask(轻量级,适合快速开发RESTful API)
- 前端框架:Vue3 + Element Plus(组件化开发效率高)
- 数据存储:SQLite(开发阶段)+ PostgreSQL(生产环境)
- 爬虫工具:Scrapy + BeautifulSoup(稳定成熟的选择)
- NLP处理:spaCy + NLTK(基础文本处理足够用)
选择Flask而非Django的原因是新闻聚合对admin等重型功能需求低,而Vue3的Composition API让复杂的前端状态管理更清晰。我曾尝试用Django REST Framework,但发现30%的封装功能实际用不上。
2.2 关键组件交互流程
graph TD A[爬虫集群] -->|原始数据| B(Flask API) B --> C[NLP处理模块] C --> D[分类/去重/摘要] D --> E[PostgreSQL] E --> F[Vue前端] F --> G[用户交互数据] G --> B实际开发中发现:当爬虫频率超过5次/分钟时,有23%的网站会返回403。解决方案是在爬虫中随机插入1-3秒延迟,并轮换User-Agent。具体配置见下文爬虫章节。
3. 核心模块实现细节
3.1 智能爬虫系统
采用分布式爬虫架构,关键配置参数:
# scrapy爬虫示例配置 class AINewsSpider(scrapy.Spider): name = 'ai_news' download_delay = random.uniform(1.0, 3.0) # 反反爬关键参数 custom_settings = { 'USER_AGENT': get_random_user_agent(), # 自定义轮换逻辑 'DEPTH_LIMIT': 2 # 控制爬取深度 } def parse(self, response): # 使用Readability算法提取正文 raw_text = extract_main_content(response.body) yield { 'title': extract_with_xpath(response, '//h1'), 'content': clean_html(raw_text), 'source': response.url }避坑经验:
- 对Medium等动态加载站点,需要配合Splash渲染
- arXiv的PDF摘要需特别处理,推荐使用
arxiv官方库 - 遇到Cloudflare防护时,可以尝试:
- 降低并发数(CONCURRENT_REQUESTS=1)
- 启用AutoThrottle扩展
- 使用付费代理服务(需评估成本)
3.2 NLP处理流水线
文本处理流程分四个阶段:
- 去重检测:SimHash算法(比传统哈希更适应文本微调)
- 关键信息提取:
def extract_keywords(text): doc = nlp(text) return [chunk.text for chunk in doc.noun_chunks if chunk.root.pos_ in ('NOUN', 'PROPN')] - 自动摘要:基于TextRank算法的改进版
- 分类打标:预训练BERT模型+自定义微调
实测发现,对于技术类新闻,保留名词短语的效果比单纯提取关键词更准确。在1000篇测试样本中,分类准确率达到89%。
3.3 前后端交互设计
Flask API的典型端点示例:
@app.route('/api/news', methods=['GET']) def get_news(): page = request.args.get('page', 1, type=int) per_page = 15 # 经过AB测试确定的最佳值 query = News.query.filter_by(verified=True) paginated = query.paginate(page=page, per_page=per_page) return { 'items': [item.to_dict() for item in paginated.items], 'total': paginated.total }前端采用Vue3的Composition API实现无限滚动:
// Vue3组件示例 setup() { const newsList = ref([]) const loading = ref(false) const page = ref(1) const loadMore = async () => { if (loading.value) return loading.value = true const res = await axios.get(`/api/news?page=${page.value}`) newsList.value.push(...res.data.items) page.value++ loading.value = false } onMounted(() => { window.addEventListener('scroll', handleScroll) }) }4. 部署与优化实战
4.1 性能调优记录
初始版本在1000篇新闻数据时,列表加载需要2.3秒。通过以下优化降至480ms:
- 数据库层面:
- 添加复合索引:
CREATE INDEX idx_news ON news (pub_date DESC, category) - 启用连接池:
SQLALCHEMY_POOL_SIZE=20
- 添加复合索引:
- 前端层面:
- 实现虚拟滚动(vue-virtual-scroller)
- 图片懒加载(v-lazy指令)
- 缓存策略:
- Redis缓存热点数据
- ETag协商缓存
4.2 生产环境部署
使用Docker Compose编排服务:
version: '3' services: web: build: ./web ports: - "5000:5000" environment: - FLASK_ENV=production redis: image: redis:alpine postgres: image: postgres:13 volumes: - pgdata:/var/lib/postgresql/data关键安全配置:
- Flask的SECRET_KEY必须从环境变量读取
- CORS设置要精确到前端域名
- 数据库连接字符串禁用明文存储
5. 典型问题解决方案
5.1 内容去重难题
初期发现不同源对同一事件的报道重复率高达40%。最终解决方案:
- 标题相似度(Levenshtein距离<0.3)
- 正文关键实体匹配(组织名+人名+时间)
- 人工标注样本训练二分类模型
5.2 时效性保障
采用分级更新策略:
- 高频源(如Twitter):每15分钟检查
- 中频源(技术博客):每小时抓取
- 低频源(学术论文):每日同步
通过Celery实现定时任务:
@app.celery.task def scheduled_crawl(): high_freq_sources = ['twitter.com', 'arxiv.org'] for source in high_freq_sources: crawl.delay(source)6. 项目演进方向
当前系统已稳定运行8个月,日均处理新闻条目1200+。后续计划:
- 增加个性化推荐(基于用户阅读历史)
- 开发浏览器插件版
- 实验GPT-4生成技术要点速览
这个项目的最大收获是:用合适的技术组合解决具体问题,比追求"高大上"的架构更重要。比如最初考虑用Kubernetes部署,后来发现单机Docker完全能满足日均5万PV的需求。