1. 项目概述当RSS阅读器遇上AI摘要如果你和我一样每天需要追踪几十个甚至上百个技术博客、新闻网站和行业动态那你一定对RSS订阅又爱又恨。爱的是它能将所有信息源聚合在一个地方恨的是信息过载——点开一个标题可能是一篇几千字的深度长文也可能只是一条简讯你不得不花费大量时间进行筛选和判断。RSS-GPT这个项目就是为了解决这个痛点而生的。它的核心思路非常直接利用AI特别是像GPT这样的语言模型来自动化处理你订阅的RSS源为每篇文章生成一个简洁、准确的摘要让你在信息流中快速抓住核心决定是否深入阅读。简单来说RSS-GPT是一个自动化工具链。它定时抓取你配置的RSS订阅源将获取到的文章内容标题、链接、全文或摘要发送给AI模型进行处理请求模型生成一个凝练的总结最后将“原文标题 AI摘要”以一种易于消费的形式比如推送到Telegram、发送邮件、保存到Notion或数据库呈现给你。这不仅仅是简单的“提取前几句”而是理解文章主旨、提炼关键论点和结论的智能摘要。这个项目适合谁呢首先是信息重度依赖者比如技术研究者、市场分析师、内容创作者和任何需要保持行业前沿敏感度的人。其次它也适合那些对RSS和自动化如Python、API调用有一定兴趣的开发者因为项目的部署和定制需要一些动手能力。最后对于想要学习如何将现有AI能力如OpenAI API与实用工具结合解决具体场景问题的朋友来说RSS-GPT也是一个绝佳的练手项目。它用相对清晰的架构展示了从数据获取、处理到分发的完整流程。2. 核心架构与工作流拆解要理解RSS-GPT如何工作我们需要把它拆解成几个核心模块。整个系统遵循着“获取 - 处理 - 输出”的经典数据处理流水线。2.1 模块化设计思路一个健壮的RSS-GPT系统通常包含以下四个核心模块这种模块化设计使得每个部分都可以独立替换或升级比如更换RSS解析库、切换不同的AI模型API或者增加新的通知渠道。RSS源获取与解析模块这是数据入口。它的职责是定时或按需从互联网上抓取你指定的RSS或Atom订阅源。这不仅仅是下载一个XML文件那么简单还需要处理网络请求超时、源格式不标准、文章编码等问题。解析后我们需要提取出每篇文章的结构化数据唯一标识GUID或链接、标题、原文链接、发布时间、以及最重要的——文章内容。有些RSS源只提供摘要这就需要模块具备“全文抓取”能力根据原文链接再去爬取完整内容。内容去重与缓存模块这是一个至关重要的“守门员”。RSS源更新时可能会重复推送同一篇文章或者你的抓取频率过高导致重复处理。这个模块需要记录已经处理过的文章标识例如将文章的GUID或链接哈希后存入一个简单的数据库或文件每次抓取到新文章时先进行比对过滤掉已经摘要过的内容避免浪费API调用次数和产生重复信息。AI摘要生成模块这是系统的“大脑”。它接收从RSS解析来的文章纯文本内容然后构造一个恰当的提示词Prompt调用AI模型的API如OpenAI的GPT-3.5/4或开源的ChatGLM、通义千问等模型的API请求其生成摘要。这里的挑战在于如何设计提示词让AI能稳定输出格式统一、重点突出、不带幻觉的摘要。同时需要处理API的调用失败、速率限制和长文本的分块处理。结果推送与持久化模块这是价值输出的“手脚”。摘要生成后需要把它送到你面前。常见的方式有发送到Telegram Bot、写入Slack频道、发送电子邮件、保存到Notion数据库、或者存入SQLite/MySQL等数据库中供其他系统查询。这个模块决定了你最终以何种形式消费这些摘要。2.2 数据流转与状态管理整个工作流的数据流转是这样的定时触发器如Cron Job启动流程 - RSS模块抓取并解析出新文章列表 - 去重模块过滤掉已处理文章 - 对于每篇新文章AI模块获取其全文并生成摘要 - 推送模块将摘要结果发送到指定目的地。状态已处理文章ID的管理是关键它保证了系统的幂等性即无论运行多少次同一篇文章只被摘要一次。通常一个轻量级的SQLite数据库足以胜任这个工作记录文章ID、源URL、处理时间和摘要结果。注意在实际部署中务必为这个状态数据库做好备份。如果丢失了处理记录系统可能会重新处理大量历史文章导致API调用激增和推送信息爆炸。3. 关键技术点深度解析理解了架构我们深入看看实现过程中的几个关键技术点和决策背后的逻辑。3.1 RSS解析与全文抓取的权衡RSS源的质量参差不齐。理想的源在item里提供完整的content:encoded标签。但很多网站为了引流只在description里放一小段摘要甚至只是一个开头。因此是否以及如何进行全文抓取是一个核心决策。策略一仅使用RSS摘要。优点是简单、快速、节省资源。如果RSS提供的摘要已经足够长例如300字以上AI模型基于此生成摘要可能也还行。但风险是信息不完整可能导致AI摘要失真。策略二智能全文抓取。这是更可靠的方案。当检测到RSS内容过短时自动根据link标签指向的原文URL使用像requests、httpx这样的库去抓取网页。然后需要用BeautifulSoup或lxml这样的HTML解析库通过识别特定的CSS选择器如.article-content,#post-body来提取正文并清理掉导航栏、广告、评论等噪音。这个过程需要为不同的网站配置不同的选择器规则维护成本较高。策略三使用第三方提取服务。例如调用mercury原readability的API或使用newspaper3k、trafilatura这类智能提取库。它们能自动识别网页主体内容通用性更强但可能引入额外的依赖、费用或延迟。我的实操心得是采用混合策略。对于你长期订阅的、固定的几个核心源花点时间配置精确的全文抓取规则稳定性最好。对于大量不固定的或次要的源可以先尝试用newspaper3k这类通用提取器如果效果不佳再考虑仅用RSS摘要。在代码中这可以体现为一个优先级列表或一个可配置的源规则表。3.2 提示词工程让AI成为你的摘要专家直接对AI说“请为这篇文章写个摘要”效果可能很不稳定。好的提示词是高质量输出的保证。设计提示词时要考虑角色、任务、格式和约束。一个经过实战检验的提示词模板如下你是一个专业的科技文章摘要助手。请根据用户提供的文章内容生成一个简洁、准确的中文摘要。 摘要要求 1. 长度控制在80-120字之间。 2. 必须包含文章的核心论点、主要发现或关键结论。 3. 保持客观不要添加原文中没有的个人评价或推测。 4. 如果原文涉及具体数据、方法或工具请在摘要中提及。 5. 摘要语言应流畅、连贯直接陈述事实。 文章标题[此处插入文章标题] 文章内容[此处插入文章正文] 请开始生成摘要这个提示词明确了AI的角色专业摘要助手限定了输出格式中文80-120字规定了内容要点核心论点、关键结论、具体数据并给出了负面约束不添加评价。将文章标题和内容作为提示词的一部分插入能帮助模型更好地理解上下文。注意事项长度控制在提示词中明确字数范围比在代码中截断更有效因为AI会在生成时就有意识地控制。处理长文GPT等模型有上下文长度限制。如果文章超过限制如GPT-3.5-turbo的16K需要先将文章分割成有重叠的块分别总结再对分块摘要进行二次总结。这会显著增加API调用成本和复杂度。一个折中方案是对于过长的文章优先使用RSS摘要或抓取文章的前N个字符例如前8000字进行处理。模型选择gpt-3.5-turbo性价比高适合大多数摘要任务。gpt-4在理解复杂逻辑和长文档方面更强但成本也高出一个数量级。可以根据摘要质量要求进行选择。3.3 推送渠道的选择与集成推送环节直接影响用户体验。选择哪种渠道取决于你的使用习惯和信息消费场景。推送渠道优点缺点适用场景Telegram Bot即时性强支持富文本加粗、链接可创建频道或群组共享跨平台好API简单稳定。需要科学上网在合规前提下使用合法国际通信工具信息流容易被其他聊天淹没。个人即时查看小团队信息共享。电子邮件无需额外App所有设备都能收便于归档和搜索可通过邮件规则分类。即时性较差容易被当作垃圾邮件格式相对简单。对即时性要求不高喜欢邮件工作流的用户或作为备份通道。Slack/钉钉等办公软件可与团队工作流深度集成支持机器人交互。通常需要组织权限个人使用稍显繁琐。团队内部的信息同步和知识库建设。Notion/Database结构化存储便于后期检索、整理和知识管理可与Notion其他页面联动。实时性一般API调用可能有频率限制。构建个人或团队的摘要知识库用于长期积累和回顾。控制台输出/日志文件最简单零依赖用于调试和验证流程。无法主动触达用户。开发调试阶段。我的建议是至少实现两种推送方式例如Telegram即时提醒 Notion归档管理。这样既能第一时间获知更新又能有一个整洁的知识库供日后查阅。代码实现上应该将推送模块抽象成统一的接口例如一个Notifier类不同的渠道作为具体实现方便扩展。4. 从零开始构建你的RSS-GPT理论说得再多不如动手做一遍。下面我将以一个使用Python集成OpenAI API和Telegram Bot的版本为例带你走一遍核心实现流程。假设我们的项目名为my_rss_gpt。4.1 环境准备与依赖安装首先确保你的机器上安装了Python 3.8。创建一个新的虚拟环境是个好习惯。mkdir my_rss_gpt cd my_rss_gpt python -m venv venv # Windows: venv\Scripts\activate # Linux/Mac: source venv/bin/activate然后安装核心依赖库。我们将使用feedparser解析RSSrequests进行网络请求openai调用APIpython-telegram-bot用于Telegram推送sqlite3Python内置进行状态管理BeautifulSoup4用于可能的全文抓取。pip install feedparser requests openai python-telegram-bot beautifulsoup4 html2text # html2text 用于将HTML内容转换为纯文本方便AI处理接下来你需要准备几个关键的API密钥和令牌OpenAI API Key在OpenAI平台注册并获取。Telegram Bot Token在Telegram中找BotFather创建一个新的Bot它会给你一个Token。你的Telegram Chat ID给你创建的Bot发一条消息然后访问https://api.telegram.org/botYourBOTToken/getUpdates就能在返回的JSON中找到你的chat_id。建议将这些敏感信息存储在环境变量中而不是硬编码在代码里。# 在.bashrc、.zshrc或系统环境变量中设置 export OPENAI_API_KEYsk-你的密钥 export TELEGRAM_BOT_TOKEN你的Bot令牌 export TELEGRAM_CHAT_ID你的Chat ID4.2 核心代码实现我们创建几个核心的Python文件来组织代码。1.config.py- 配置文件import os # RSS源列表 RSS_FEEDS [ https://feeds.feedburner.com/TechCrunch/, https://hnrss.org/frontpage, # Hacker News https://www.reddit.com/r/programming/.rss, # 添加你的订阅源 ] # AI模型配置 OPENAI_API_KEY os.getenv(OPENAI_API_KEY) OPENAI_MODEL gpt-3.5-turbo # 或 gpt-4 OPENAI_MAX_TOKENS 500 # 摘要最大长度 OPENAI_TEMPERATURE 0.3 # 较低的温度使输出更稳定、更聚焦 # Telegram配置 TELEGRAM_BOT_TOKEN os.getenv(TELEGRAM_BOT_TOKEN) TELEGRAM_CHAT_ID os.getenv(TELEGRAM_CHAT_ID) # 数据库配置 DB_PATH processed_articles.db2.database.py- 数据库管理负责记录已处理文章实现去重。import sqlite3 import hashlib from datetime import datetime def get_db_connection(): conn sqlite3.connect(processed_articles.db) conn.row_factory sqlite3.Row # 以字典形式返回行 return conn def init_db(): conn get_db_connection() conn.execute( CREATE TABLE IF NOT EXISTS processed_articles ( id TEXT PRIMARY KEY, -- 文章唯一标识的哈希值 feed_url TEXT, article_url TEXT, title TEXT, processed_at TIMESTAMP ) ) conn.commit() conn.close() def is_processed(article_id): 检查文章是否已处理 conn get_db_connection() cursor conn.cursor() cursor.execute(SELECT id FROM processed_articles WHERE id ?, (article_id,)) exists cursor.fetchone() is not None conn.close() return exists def mark_as_processed(article_id, feed_url, article_url, title): 标记文章为已处理 conn get_db_connection() conn.execute( INSERT INTO processed_articles (id, feed_url, article_url, title, processed_at) VALUES (?, ?, ?, ?, ?) , (article_id, feed_url, article_url, title, datetime.utcnow())) conn.commit() conn.close()3.rss_fetcher.py- RSS抓取与内容提取import feedparser import requests from bs4 import BeautifulSoup import html2text from urllib.parse import urlparse import hashlib def fetch_feed(feed_url): 抓取并解析RSS源 print(f正在抓取源: {feed_url}) feed feedparser.parse(feed_url) articles [] for entry in feed.entries: # 生成文章唯一ID优先使用id否则用link article_id entry.get(id, entry.link) article_hash hashlib.md5(article_id.encode()).hexdigest() article_data { id: article_hash, feed_url: feed_url, title: entry.title, link: entry.link, published: entry.get(published, ), summary: entry.get(summary, ), content: get_article_content(entry) # 获取完整内容 } articles.append(article_data) return articles def get_article_content(entry): 获取文章完整内容。 策略优先使用content如果没有或太短则尝试抓取原文。 # 1. 检查是否有完整的content if hasattr(entry, content): for item in entry.content: if item.type text/html and len(item.value) 500: # 认为内容足够长 return html2text.html2text(item.value) # 2. 检查summary是否足够长 if entry.get(summary) and len(entry.summary) 500: return html2text.html2text(entry.summary) # 3. 尝试从原文链接抓取 print(f - 内容过短尝试抓取原文: {entry.link}) try: response requests.get(entry.link, timeout10, headers{User-Agent: Mozilla/5.0}) response.raise_for_status() soup BeautifulSoup(response.content, html.parser) # 尝试一些常见的正文选择器这里可以扩展 selectors [article, .post-content, .entry-content, #content, main] for selector in selectors: element soup.select_one(selector) if element: # 清理不需要的元素 for tag in element([script, style, nav, footer, aside]): tag.decompose() return html2text.html2text(str(element)) # 如果没找到回退到整个body return html2text.html2text(soup.body.get_text() if soup.body else ) except Exception as e: print(f - 抓取原文失败: {e}) return entry.get(summary, ) # 最终回退到摘要4.ai_summarizer.py- AI摘要生成import openai from config import OPENAI_API_KEY, OPENAI_MODEL, OPENAI_MAX_TOKENS, OPENAI_TEMPERATURE openai.api_key OPENAI_API_KEY def generate_summary(title, content): 调用OpenAI API生成摘要 if not content or len(content.strip()) 50: return [内容过短无法生成有效摘要] # 构造提示词 prompt f你是一个专业的科技文章摘要助手。请根据用户提供的文章内容生成一个简洁、准确的中文摘要。 摘要要求 1. 长度控制在80-120字之间。 2. 必须包含文章的核心论点、主要发现或关键结论。 3. 保持客观不要添加原文中没有的个人评价或推测。 4. 如果原文涉及具体数据、方法或工具请在摘要中提及。 5. 摘要语言应流畅、连贯直接陈述事实。 文章标题{title} 文章内容 {content[:6000]} # 限制输入长度避免超出token限制 请开始生成摘要 try: response openai.ChatCompletion.create( modelOPENAI_MODEL, messages[ {role: system, content: 你是一个专业的文本摘要助手。}, {role: user, content: prompt} ], max_tokensOPENAI_MAX_TOKENS, temperatureOPENAI_TEMPERATURE, ) summary response.choices[0].message.content.strip() return summary except openai.error.OpenAIError as e: print(fOpenAI API调用错误: {e}) return f[摘要生成失败: {e}]5.notifier.py- 结果推送import telegram from telegram import ParseMode from config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID def send_to_telegram(title, link, summary): 发送摘要到Telegram if not all([TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID]): print(Telegram配置不完整跳过推送) return False message f*{title}*\n\n{summary}\n\n[阅读原文]({link}) bot telegram.Bot(tokenTELEGRAM_BOT_TOKEN) try: bot.send_message( chat_idTELEGRAM_CHAT_ID, textmessage, parse_modeParseMode.MARKDOWN, disable_web_page_previewFalse ) print(f 已推送至Telegram: {title[:50]}...) return True except telegram.error.TelegramError as e: print(fTelegram推送失败: {e}) return False # 可以在这里扩展其他推送方式如send_to_email, save_to_notion等6.main.py- 主流程控制器这是将所有模块串联起来的脚本。import time from config import RSS_FEEDS from database import init_db, is_processed, mark_as_processed from rss_fetcher import fetch_feed from ai_summarizer import generate_summary from notifier import send_to_telegram def main(): print( RSS-GPT 摘要服务启动 ) init_db() # 初始化数据库 for feed_url in RSS_FEEDS: print(f\n处理订阅源: {feed_url}) try: articles fetch_feed(feed_url) print(f 获取到 {len(articles)} 篇文章) for article in articles: # 1. 去重检查 if is_processed(article[id]): print(f 跳过已处理文章: {article[title][:60]}...) continue print(f 处理新文章: {article[title]}) # 2. 生成AI摘要 summary generate_summary(article[title], article[content]) print(f 摘要生成完毕) # 3. 推送结果 (这里以Telegram为例) send_to_telegram(article[title], article[link], summary) # 4. 标记为已处理 mark_as_processed( article[id], article[feed_url], article[link], article[title] ) # 短暂延迟避免请求过快 time.sleep(2) except Exception as e: print(f处理源 {feed_url} 时发生错误: {e}) continue print(\n 所有订阅源处理完毕 ) if __name__ __main__: main()4.3 部署与自动化运行本地测试成功后你需要让它自动定时运行。最经典的方式是使用服务器的Cron Job。确保依赖和脚本可访问将整个my_rss_gpt文件夹上传到你的服务器或云函数、容器环境。创建Cron任务使用crontab -e编辑定时任务。例如每30分钟运行一次*/30 * * * * cd /path/to/your/my_rss_gpt /path/to/your/venv/bin/python main.py /path/to/log/rss_gpt.log 21这条命令会每30分钟切换目录到项目下用虚拟环境中的Python执行main.py并将所有输出包括错误追加到日志文件中。考虑使用云服务如果你没有常驻服务器可以考虑使用GitHub Actions可以设置定时任务免费额度足够个人使用。将代码和密钥作为GitHub Secrets放在仓库里让Actions定时运行你的脚本。云函数如AWS Lambda Google Cloud Functions 阿里云函数计算等。它们按需执行成本极低但需要将项目打包成特定格式。容器化部署使用Docker将整个环境打包可以在任何支持容器的地方运行管理起来更干净。5. 常见问题、优化与避坑指南在实际搭建和使用过程中你肯定会遇到各种问题。下面是我踩过坑后总结的一些经验和优化建议。5.1 典型问题排查速查表问题现象可能原因排查步骤与解决方案抓取不到文章或内容为空1. RSS源地址错误或失效。2. 网络问题被墙或超时。3. 网站反爬需要User-Agent或Cookies。4.feedparser解析特定格式有问题。1. 用浏览器直接访问RSS地址验证。2. 在服务器上curl测试连通性。3. 在requests请求中添加合理的headers如User-Agent。4. 尝试使用feedparser的bozo属性检查解析错误。AI摘要质量差胡言乱语或无关1. 提示词设计不佳。2. 输入给AI的文章内容噪音太多广告、导航栏。3. 文章本身内容质量差或非文本为主。4. 模型温度Temperature参数过高。1. 优化提示词明确角色、任务和格式要求。2. 加强全文抓取后的内容清洗使用更精准的CSS选择器或newspaper3k。3. 在抓取阶段过滤掉太短或非文章类内容如视频页。4. 将temperature调低如0.2-0.3。Telegram推送失败1. Bot Token或Chat ID错误。2. 消息内容格式有误如Markdown语法错误。3. 网络问题导致API请求失败。4. Bot被用户屏蔽或群组/频道权限不足。1. 重新核对Token和Chat ID确保Bot已启动并已发送/start。2. 简化消息内容先发送纯文本测试。3. 检查服务器网络添加重试机制。4. 确认Bot在对应聊天中有发送消息的权限。重复推送同一篇文章1. 去重逻辑失效文章ID生成方式不稳定。2. 数据库未正确写入或读取。3. RSS源本身重复推送。1. 确保文章ID生成基于稳定字段如guid或link。2. 检查数据库文件权限和SQL语句。3. 在去重检查时可以结合published时间忽略过早的重复项。API调用超限或费用激增1. 抓取频率过高文章太多。2. 长文章未分块消耗大量token。3. 错误循环导致重复调用API。1. 降低Cron执行频率或在代码中限制单次处理文章数量如前10篇。2. 实现长文分块摘要逻辑或直接截断处理。3. 加强异常处理和日志记录监控API用量。5.2 高级优化与扩展思路当基础版本运行稳定后你可以考虑以下优化来提升体验和可靠性异步处理提升效率使用asyncio和aiohttp库可以同时抓取多个RSS源和处理多篇文章大幅缩短单次运行时间。摘要缓存与去重对于热门文章可能被多个源转载。可以在AI摘要前对文章内容进行向量化如用Sentence-BERT生成嵌入计算相似度对高度相似的文章直接使用已有的摘要避免重复调用AI。摘要质量评分与过滤不是所有文章都值得摘要。可以先用一个简单的规则如关键词匹配、来源网站权重或一个快速的AI分类调用来过滤掉广告、软文或你完全不感兴趣领域的内容。支持更多AI后端不要绑定在OpenAI一家。可以抽象出LLMProvider接口轻松接入Claude、Gemini、国内大模型如DeepSeek、智谱GLM或本地部署的Ollama模型根据成本、速度和效果灵活选择。构建Web管理界面使用Flask或FastAPI搭建一个简单的Web界面方便动态添加/删除RSS源、查看摘要历史、手动触发抓取任务等。实现优先级队列为不同的订阅源设置不同的优先级。高优先级的源如核心行业博客立即推送低优先级的源如综合新闻可以攒一批在一天结束时汇总成一份“每日摘要”推送。5.3 成本控制与监控使用AI API最大的顾虑就是成本。以下是一些控制成本的实用技巧设置预算硬顶在OpenAI后台设置使用量预算和硬性限制。监控Token用量OpenAI的响应里会包含使用的token数量。可以在代码中记录并估算每次调用的成本定期复盘。内容长度截断如前所述严格限制发送给AI的文本长度。对于新闻类文章前2000字通常包含了绝大部分关键信息。选择性价比模型对于摘要任务gpt-3.5-turbo在绝大多数情况下已经足够好其成本远低于gpt-4。失败重试与降级如果AI API调用失败如超时可以设置重试。如果多次失败可以降级为简单的文本提取如提取前两段作为摘要而不是直接报错。搭建并运行起自己的RSS-GPT后最大的感受是信息焦虑确实减轻了。我不再需要频繁地、焦虑地刷新各个网站也不再害怕错过重要信息。每天定时收到的几条精炼摘要让我能快速把握行业动态只在真正感兴趣时才点开原文深度阅读。这个项目就像一个不知疲倦的、专注的助理帮你完成了信息筛选中最耗时的那部分工作。从技术实现上看它也是一个完美的练手项目涵盖了网络请求、数据解析、API集成、状态管理和任务调度等多个实用技能点。你可以从最简单的版本开始然后根据自己的需求一点点添加新功能比如我后来就增加了根据摘要关键词自动打标签并同步到我的笔记软件中的功能让信息流最终沉淀为知识库。