ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

手把手搭建AI资讯聚合平台:从爬虫到大模型推送的完整技术栈

手把手搭建AI资讯聚合平台:从爬虫到大模型推送的完整技术栈 1. 为什么我决定自己搭每天被AI信息淹没的体验过去两年我养成了一个非常不好的习惯每天早上睁眼第一件事就是刷各种AI资讯。微信公众号、知乎、arXiv、GitHub Trending、Product Hunt、Reddit的r/MachineLearning……每个平台都有自己的推荐算法和内容风格但信息高度重叠。今天OpenAI发了个新模型明天Google出了篇论文后天某个开源项目冲上GitHub热榜——同一件事我能从八个渠道看到八遍不同角度的解读。真正让我崩溃的是某一周的周四那天至少有四条重要新闻同时爆发我为了追完所有细节在六个平台之间来回切换花了一整个上午。下午看总结的时候发现真正对我有用的信息不超过三条其余全是重复报道、营销软文和标题党。那一刻我突然想明白了一个问题我需要的是一个AI资讯聚合平台能用一套自动化流程把散落在各处的AI动态收集起来过滤掉重复内容再用大模型帮我提炼核心信息最后推送给我。与其等别人做的聚合产品把规则改来改去不如自己动手搭一个只属于我的版本。这个项目做下来收获比我想象中大得多。它不光是解决了我个人的信息焦虑还让我把爬虫、消息队列、大模型API调用、前端展示、定时任务调度这一整条技术链路完整地走了一遍。无论你是做后端的、做前端的还是刚入门想找个完整项目练手的开发者这篇文章里的拆解思路、踩坑记录和选型逻辑都能让你少走不少弯路。我会尽量把为什么这么设计讲透而不是只丢给你一段能跑的代码。2. 整体架构一条从信息源到手机通知的自动化流水线先说结论一个能稳定跑起来的AI资讯聚合平台核心不是爬虫写得多漂亮也不是前端做得有多炫而是整条数据管线的可靠性。我把它拆成了四个模块——采集层、清洗层、AI处理层、展示与推送层。每一层各司其职层与层之间通过消息队列解耦这样任何一个环节挂了都不会把整条链路拖死。2.1 四个核心模块的职责划分采集层负责定时抓取各个信息源的内容包括RSS订阅、网页正文、GitHub热门仓库、arXiv论文摘要。它只做一件事把原始内容塞进消息队列不关心后续怎么处理。清洗层从队列里拿到原始内容后做正文提取、HTML标签去除、编码修复和URL去重。这一层最大的挑战是信息源的格式差异极大——同样是RSS有的给全量正文有的只有摘要同样是GitHub仓库README里可能混着大量无关的徽章图片和表格。清洗层的目标是把这些异构数据统一成结构化的条目。AI处理层是整条流水线的中枢。它负责对清洗后的每条资讯做三件事标题重写、核心摘要生成、标签分类。我用的方案是大模型API加少量Python规则兜底具体怎么设计提示词、怎么控成本后面单独开一节细说。展示与推送层把处理好的结构化数据写入数据库通过一个轻量的Web前端展示同时按用户配置的规则把每日精选推送到消息通道。这一层直接决定你每天愿不愿意打开它。2.2 技术选型为什么是这些而不是那些很多教程喜欢直接丢一张技术栈清单却不解释原因。我把自己实际用下来的选型和对比如下模块选型备选方案选择理由抓取框架Python Requests BeautifulSoupScrapy、PlaywrightAI资讯站大多是服务端渲染或轻量反爬Requests足够需要执行JS的少数站点用Playwright单独处理消息队列Redis StreamRabbitMQ、Kafka单机部署场景下Redis Stream够用且运维成本低自带消费组天然适合多消费者场景主数据库PostgreSQLSQLite、MySQL资讯数据带全文检索需求PostgreSQL内置的全文检索能力对中文场景够用配合pgvector还能做向量检索缓存与去重Redis无布隆过滤器、SimHash比对、最新资讯热榜缓存全压在Redis上性能足够API服务FastAPIFlask、Django异步支持和Pydantic数据校验是刚需前端界面配合Jinja2模板直接渲染不额外搭前后端分离大模型调用OpenAI兼容接口各家国产模型API只依赖OpenAI的Chat Completions协议这样换模型厂商不用改代码配置一个base_url就行定时调度APSchedulerCelery Beat、系统crontabCelery对单机项目太笨重APScheduler嵌在API进程里足够支持cron表达式控制抓取节奏这套组合跑在单台2核4G的云服务器上月成本控制在几十块以内。如果你不想维护数据库也可以把PostgreSQL换成SQLite把Redis Stream简化成一张带状态标记的MySQL表——牺牲一点并发能力换来的是部署复杂度大幅降低。2.3 数据流设计为什么中间要夹一个消息队列最简单的实现方式是采集完直接写数据库然后AI处理层轮询数据库。我一开始就是这么干的跑了两天就发现问题采集层抓取速度不均匀有时候一个小时内同时抓到两三百条有时候半小时只有一两条。AI处理层调用大模型API是有并发限制和费用消耗的如果采集层写完数据库直接触发AI调用高峰期会把API配额瞬间打爆。后来我改成采集层只负责往Redis Stream里塞原始消息AI处理层按固定的速率从队列里取消息处理。这样相当于给整条流水线加了一个缓冲区——哪怕某个信息源突然爆发一千条更新队列先扛住AI层还是按自己的节奏匀速消费。实测下来这种方式显著减少了API调用HTTP 429限流错误的出现频率。我还给每条消息设计了状态机pending等待处理、summarizingAI处理中、done处理完成、failed处理失败。AI处理失败的消息会在Redis里记下重试次数超过三次就进入死信队列等周末人工排查一次。这个设计不复杂但非常有用——头条新闻的抓取偶尔会遇到正文结构异常没有死信机制这些消息会一直卡在队列里占用内存。3. 信息源抓取与内容去重最花时间、最容易翻车的一层很多想做资讯聚合的人上来就问你用了什么神器爬虫框架实际上爬虫代码只占整个项目工作量的三成剩下七成都在处理一个极其烦人的问题反爬规避和内容去重。如果把精力放错地方后期维护会让人崩溃。3.1 信息源清单与适配策略我最终把信息源分成四类每类的抓取策略完全不同RSS/Atom源这是优先级最高的信息源。很多AI媒体和博客都提供RSS输出解析标准结构规整几乎不遇反爬。我用feedparser库统一解析半小时抓取一次。静态HTML页面比如某些知名AI资讯站的列表页内容是服务端渲染的。直接用Requests拿HTML再用BeautifulSoup按CSS选择器提取标题、链接、正文。这类站点一般只在首页或列表页做基本的User-Agent校验伪装成正常浏览器的请求头就能通过。动态渲染页面少数站点用Vue或React做客户端渲染直接拿HTML拿不到正文。我单独准备了一个Playwright实例无头浏览器加载页面后等待JS执行完再取内容。这个方案对服务器内存有要求2G内存的机器跑起来比较吃紧我做了个限制只有白名单里的域名才走Playwright且同时最多开两个页面实例。平台APIGitHub和Hacker News这类的开放API是最高质量的信息源。GitHub Trending有非官方APIHacker News的Algolia API支持按关键词检索这些接口返回的是结构化JSON连清洗都省了。我建议你最初搭建时优先接RSS源和平台API这两类源能让你在半天内把整条链路跑通。等核心流程稳定了再去逐步增加HTML页面源和动态页面源这样排查问题时不用面对一堆不确定因素。3.2 抓取频率与反爬的平衡宁慢勿快这里必须强调的是自用聚合平台的抓取频率设置核心原则是够用就行。我在生产环境里对RSS源设置的间隔是30分钟一次对HTML页面源是60分钟一次对GitHub API是严格按照配额来——该平台的未授权请求限制是60次每小时我设置成每小时只访问30次留足余量。很多人一上来就把并发数调到20以上恨不得一分钟内把全网资讯抓一遍。结果往往是被目标站点封IP或者导致对目标站点服务器造成压力被投诉。我一直坚持用单线程串行抓取加随机延时的方式在Requests的Session里设置统一的请求头包含常见的浏览器User-Agent。跑了大半年除了少数反爬特别严格的站点没有被封过。如果你的目标是多个人同时使用那建议购买代理池和更谨慎的抓取策略——但自用场景完全不需要现在考虑这个问题。3.3 SimHash去重让相似文章不会重复轰炸你资讯聚合场景中同一条新闻在多个渠道出现是常态。比如某大模型发布新版本可能有十几个公众号和媒体博客在报道同一个事件。若不做去重你的推送列表就会有一堆标题换汤不换药的文章。我调研过几种去重方案最简单的MD5做完全一致判断只对完全相同的内容有效数据库里的最长公共子串比较太慢最终选用SimHash算法加汉明距离。原理可以这么理解SimHash把一篇文本计算成一个64位的指纹两篇文章指纹的汉明距离越小说明相似度越高。我设定的阈值是汉明距离小于等于3就判为重复保留时间戳更早的那条丢弃后到的。SimHash在中文文本上的一个隐藏问题是对分词结果敏感。我踩过的坑是直接拿原始正文去做SimHash效果很差因为HTML标签、广告文案这些噪声被哈希进去了。后来我在计算指纹前先做了一次粗清洗去掉所有HTML标签、去掉常见的CMS追踪参数、只提取文章正文的前两千字参与计算。经过调优之后去重的命中率明显提升误判率也降到了可接受范围。如果在做这个项目时你不想自己实现SimHash可以直接用text2vec库里的简化实现或者更粗暴地使用Redis的SET结构存储标题的归一化版本效果能覆盖80%的完全重复场景。对于自用够用就好不必追求极致。4. AI处理层让大模型把资讯变成为我定制的简报这一层是整个平台的灵魂。采集层和清洗层解决的是把信息拿进来AI层解决的才是把信息变成我能消化的形态。我一开始尝试过用规则做关键词提取和摘要但效果和大模型相差太远——比如一篇讲大模型训练技巧的文章关键词列表里全是模型训练完全看不出文章的核心观点。换成大模型之后摘要质量直接从可用变成了有阅读价值。4.1 为什么选择大模型而非正则和NLP工具面对资讯摘要和分类任务传统方案需要为每个场景单独训练或调教模型通用性差、迭代成本高。大模型的主要优势在于零样本泛化能力——我只需要设计好提示词模板它就能对来自不同领域、不同语气的文章给出结构清晰的结果。我实际处理的任务分为三类标题重写原文标题往往带营销色彩如震惊AI又双叒突破我会让模型重写成中性、信息量更足的表达。核心摘要限制在100-150字提炼背景、关键结论、对从业者的影响。标签分类从预先定义的标签集合中选出最匹配的同时给出置信度排序。这三类任务在一条大模型调用里完成输出的是严格JSON格式方便程序直接解析。整体设计思路就是让大模型服务于平台的结构化目标而不是让它自由发挥写一篇小作文。4.2 提示词模板设计与实测效果我使用的提示词模板经过了几轮迭代目前的版本大致是这样的结构你是一个AI行业资讯编辑。请对以下文章执行三项操作 1. 重新生成标题去除营销夸张语气保留核心主体和关键信息 2. 生成摘要150字以内包含技术背景、核心突破、对从业者影响三个层面 3. 分类打标从[大模型, Agent应用, AI编程, AI绘画, AI搜索, AI基础设施, 开源项目, 行业动态]中选择1-3个标签。 要求只输出JSON格式如下 {title: ..., summary: ..., tags: [...]} 文章内容如下 {清洗后的正文}这套提示词在实际使用中有几个值得注意的细节一是给模型限制输出JSON格式省去了大量正则解析的麻烦二是标签集合必须严格固定否则模型会天马行空地造出十几个标签三是正文长度如果超过模型上下文限制我用截取前1500个字符的方式做头重脚轻式处理因为开头部分通常包含了文章的核心信息。实测下来GPT-4o级别的模型在这套模板上的效果很稳定摘要几乎没有废话稍微小一点的模型也够用只是偶尔会把摘要写成评论。为了避免劣质结果污染数据库我在AI层加了一个简单的规则校验摘要少于30个字或者包含明显的主观评价词如值得太好了就标记为失败并重新调用一次。4.3 成本控制一个资讯平台的API费用能压到多低算一笔账假设平均每次任务输入是1800个token输出是500个token换算成约2300个token按市面上中等偏低价位的大模型API来算单次成本约0.01元每天抓600条资讯实际有效去重后通常只有200条左右一天的全部处理成本也就2块钱上下。一个月下来几十块钱完全可以接受。但成本控制依然是必要的尤其是你的聚合平台信息源较多的时候。我用了三个手段降低消耗批量处理把多条资讯拼进同一轮对话让模型一次性输出多个JSON对象。单次请求固定开销被摊薄实测贵了约30%的上下文但省了70%的来回开销。短文本策略如果RSS源已经提供了摘要那就不需要全文重写直接用小成本模型跑一遍摘要即可只有正文质量高的资讯才动用更贵的模型。降级规则把资讯按当天是否被用户阅读来分等级。低频场景下用便宜的轻量模型先处理用户手动标记感兴趣的资讯再触发一次更高质量模型的深度摘要。成本控制的核心逻辑不是一味图便宜而是把贵的计算资源用在对用户最有价值的内容上。5. 展示层与主动推送让好的资讯找上门处理完的资讯如果只是堆在网页上和看普通新闻网站没有本质区别。聚合平台真正提升体验的地方在两点一是按用户关注领域把内容组织好二是主动把今日值得看的内容推到用户面前。我的前端做得不算复杂但信息架构经过了好几轮调整。5.1 Web端设计分类导航与我的关注流Web端我用了FastAPI加Jinja2模板配合一点轻量JavaScript做交互。首页默认展示的是综合栏目——按时间倒序展示当天处理完成的所有资讯卡片每张卡片包含标题、摘要、标签和原文链接。侧边栏是固定的标签筛选区点击某个标签后页面会展示该标签下的资讯列表。这里有一个设计细节很关键每个标签页都附带一个相似主题的推荐模块。我基于PostgreSQL里存的标签向量做简单关联推荐逻辑是提取用户当前正在浏览的资讯标签组合在数据库里搜索共享两个以上标签的最近资讯。由于资讯的标签是AI打出来的这个关联推荐的准确度意外地高。我在界面里还保留了一个原始标题区的折叠面板默认隐藏可以点击展开看到原始标题和原文正文。为什么留这个因为AI摘要偶尔可能带偏原意提供原文能避免误判——资讯聚合最重要的还是真实性。5.2 推送通道Telegram Bot和邮件双通道资讯平台最核心的功能就是主动投喂。我实现的推送规则很简单每天定时三个时间点早上8点、中午12点、晚上7点把过去8小时内新增且打标为高价值的资讯整理成一条汇总消息推送到指定通道。高价值的判定规则是标签命中用户关注的标签集合且AI摘要长度超过80字且来源权重在平均值以上。Telegram Bot的实施方案是通过官方Bot API发送消息配合HTML格式的排版做出一条含链接的摘要列表。邮件通道我用了SMTP库直接发送内容风格更正式一些。两条通道里的每条摘要都附上了打开原文的链接。实测下来推送收到的点击率远高于网页端随机浏览——这也印证了我最初的想法大家缺的其实不是资讯数量而是经过筛选和组织的精品摘要。5.3 阅读体验优化的几个小心思这里分享几个提升体验的小细节。第一每篇文章保存时会做一个/阅读时间估算推送里会显示预计3分钟读完这能帮助用户决定要不要立即点开。第二我在Web端做了今天/本周/历史三个时间维度的切换避免时间线像微博一样无限下滑。第三我允许用户对不喜欢的资讯源做折叠操作——折叠一次之后该来源的内容一周内不会出现在首页这个功能对过滤某些标题党媒体效果立竿见影。另外一个很实用的小功能是重读推荐。我每周日跑一次SQL查询找出上周被推送过但用户没有点击的高分资讯生成一封周末补读邮件。在大模型时代偶尔翻出一篇被淹没的好文章反而最有惊喜感。6. 部署上线与踩坑纪实从本机Demo到稳定运行这个项目从写完第一版能跑的代码到放在服务器上稳定运行三个月不出大问题中间经历了好几个让人崩溃的坑。我把最有价值的教训整理出来你看了能直接避开。6.1 部署拓扑与资源规划我的部署目标是单台云的虚拟主机2核4G配置阿里云或腾讯云之类的标准机型都行。系统是Ubuntu 22.04所有服务用Docker Compose编排一共四个容器API服务、PostgreSQL、Redis、定时任务。API服务和定时任务共用同一个镜像只是通过环境变量区分启动命令。如果你只用一台轻量服务器建议在买机器时把带宽选到3M以上。因为采集层和AI处理层都要访问外部网络带宽太小会导致请求超时。另一个重要的资源规划是磁盘空间PostgreSQL里如果保存了每篇资讯的原始正文一年的数据量大概会到2-3GB建议给数据卷挂一个独立的数据盘防止主系统盘被撑满。6.2 三个必须提前处理的问题时区、重试、数据库连接池时区问题。这个坑很小但极其隐蔽。PostgreSQL默认时区是UTC而我的定时推送任务用的是北京时间。头两天调试时发现推送总是晚8小时。解决方案是在所有服务和数据库的连接参数里统一指定Asia/Shanghai并且所有时间戳字段都以TIMESTAMPTZ类型存储应用层统一用ISO 8601格式传输时间。重试机制。AI处理层调用大模型API时偶尔会遇到连接超时或服务端返回5xx错误。如果不加重试资讯流程会中断。我给所有外部调用封装了一个带指数退避的重试器第一次失败等2秒重试第二次等4秒第三次等8秒最多重试三次。这个逻辑大约解决了95%的临时性错误。数据库连接池。FastAPI默认情况下每个请求新建数据库连接并发一高就会出现too many connections错误。我用psycopg2基于连接池管理设置最小5个、最大20个连接。API服务和定时任务进程各自独立维护一个连接池避免互相争抢。6.3 运行三个月后的复盘哪些设计被验证有用项目跑了一段时间后验证了几个初期的设计判断。消息队列解耦的方案被证明是完全正确的某次上游信息源出现异常一次性涌入超过两千条的重复消息队列扛住了流量峰值AI层按既定速率慢慢消费没有出现接口限流或数据库写入风暴。这个场景如果让我同步处理服务器大概率直接宕机。SimHash去重的价值也在一次大事件中体现得很明显某头部实验室发布重大进展的那天我订阅的四十多个来源里有将近三十条报道同一事件。如果没有去重当天的推送列表至少有二十五条重复内容用户会直接失去阅读欲望。去重后只保留了四条不同角度的代表性报道阅读体验好了很多。另外我原本以为标签分类这个功能只是锦上添花实际上它成了整个平台的骨干。有了标签体系后续做关键词告警、周报生成、相关推荐都变得非常顺手。如果你的平台计划增加某方面资讯重点盯梢功能请务必在最开始就把标签的准确性做扎实。7. 这个项目后续还能怎么扩展我列了几个正在考虑的方向搭建到现在这个阶段整个平台已经完全自洽了。但我心里清楚资讯聚合这件事还能往更智能的方向走。第一个方向是引入多AI协作机制。目前AI处理层只有单次调用但复杂任务比如判断一条资讯是否值得深度阅读可能需要两个模型先各出意见再汇总。我在阅读热词里看到多AI协作这个概念频繁出现也已经在本地做了原型验证准备把它整合进摘要质量评估模块。第二个方向是向量检索。PostgreSQL里已经可以跑pgvector扩展如果我把每篇文章的摘要向量化存储就能实现语义相似文章的检索。这比当前基于标签的关联推荐要强大得多比如你正在看一篇关于Agent记忆机制的深度文章系统能推荐出几篇并未共用标签但语义上真正相关的内容。第三个方向是互动反馈闭环。目前推送出去的内容是否被点开阅读我只有点击率这一个粗略指标。下一步我想在每篇文章下加有用/没用按钮把反馈数据喂给标签权重计算和摘要生成提示词调整实现真正的个性化学习。我的体会是搭建这类平台最大的价值反而不是最终产物而是过程中对整个AI技术生态有了更系统化的认知。在一个信息过载的时代拥有一个完全为自己定制的资讯入口那种信息主动来找我的掌控感值得每个重度知识工作者体会一次。
返回列表