当前位置: 首页 > news >正文

使用n8n+飞书搭建自动推送新闻机器人

运行效果

点击查看原文,可以跳转到新闻的36氪链接。

n8n工作流

主要功能

实现从36氪上爬取新闻,并筛选和AI相关的AI类新闻,最终将新闻的结果,推送到手机端。

工作流搭建与配置

定时器

设置成定时触发流程,可以选择按日/分钟/月/周等等,选择范围还是很广的。我设置成了按天,每天触发一次,时间为上午10点。

Http请求节点

后面用http请求节点,主要是为了抓取36氪的新闻。RSS是一个能让你在一个地方订阅各种感兴趣网站的工具

这里网址需要填36氪新闻的RSS订阅网址,也就是https://36kr.com/feed

节点配置信息如下:

只需要将method设置为get,然后网址url设置成36氪新闻的RSS订阅地址就行啦。

可以点击Execute Step去测试一下,结果为:

AI类新闻筛选

由于返回的数据有很多篇新闻,所以后面加了一个Code节点,来从中筛选数据。这里采用关键词匹配,也就是如果返回的结果中,在title标题、content内容中,如果包含'AI', '人工智能', '大模型', 'LLM', 'GPT', 'Claude', 'Gemini','通义千问', '文心一言', '豆包', '讯飞星火', 'AI Agent','机器学习', '深度学习', '神经网络', 'NLP', 'CV', 'AIGC'等词汇,就认为是AI类新闻。

这些关键词可以根据个人需求,再做一些增补。或者再增加一些语义相关的匹配去检索和AI相关的新闻,例如词向量的余弦相似度等。

代码选择使用JavaScript语言,对应的代码如下:

try { const rssData = $input.item.json.data || $input.item.json; if (!rssData) { console.log('RSS数据为空'); return []; } function parseAndFilterRSS(xmlString) { const items = []; // 提取所有item const itemMatches = xmlString.match(/<item[^>]*>[\s\S]*?<\/item>/gi); if (!itemMatches) { console.log('未找到RSS item'); return items; } const aiKeywords = [ 'AI', '人工智能', '大模型', 'LLM', 'GPT', 'Claude', 'Gemini', '通义千问', '文心一言', '豆包', '讯飞星火', 'AI Agent', '机器学习', '深度学习', '神经网络', 'NLP', 'CV', 'AIGC' ]; const lowerKeywords = aiKeywords.map(k => k.toLowerCase()); for (const itemXml of itemMatches) { const title = (itemXml.match(/<title[^>]*>([\s\S]*?)<\/title>/) || [])[1] || ''; const link = (itemXml.match(/<link[^>]*>([\s\S]*?)<\/link>/) || [])[1] || ''; const contentSnippet = (itemXml.match(/<description[^>]*>([\s\S]*?)<\/description>/) || [])[1] || ''; const pubDate = (itemXml.match(/<pubDate[^>]*>([\s\S]*?)<\/pubDate>/) || [])[1] || ''; const fullText = (title + ' ' + contentSnippet).toLowerCase(); const isAiRelated = lowerKeywords.some(keyword => fullText.includes(keyword)); if (isAiRelated) { items.push({ title: title.trim(), link: link.trim(), contentSnippet: contentSnippet.trim(), pubDate: pubDate.trim() }); } } return items; } const result = parseAndFilterRSS(rssData); console.log('AI相关新闻数量:', result.length); return result; } catch (e) { console.error('RSS解析/过滤出错:', e.message); return []; }

配置执行结果如下:

数据清洗节点

因为后面在飞书上,想要实现推送,并且用户可以点击推送的链接,跳转到对应的36氪新闻网址上。而我之前在实现的时候,如果不加数据清洗节点,则遇到两个问题:1)飞书的推送有数量限制,当短时间一次性推送数量过多时,会出现警告语限制。2)原来抓取的新闻数据中,link链接是类似于<![CDATA[https://36kr.com/p/3840996342073604?f=rss]]>这样的数据,需要再从中做一下处理,才能解析出网页。

所以,为了解决这两个问题,我又加了一个数据清洗节点,选择的是code节点,然后用JavaScript代码,对应代码如下:

// 拿到输入的所有数据 const items = $input.all(); // 定义清洗CDATA的函数(修复版) const cleanCdata = (str) => { if (!str) return ''; // 去掉 <![CDATA[ 和 ]]> 标签,保留内容 return str.replace(/<!\[CDATA\[/g, '').replace(/]]>/g, '').trim(); }; // 对每一条数据进行清洗 const processed = items.map(item => { const title = cleanCdata(item.json.title); const link = cleanCdata(item.json.link); const pubDate = item.json.pubDate || '未知时间'; return { title, link, pubDate }; }); // 输出前5条 return processed.slice(0, 5);

代码对每一条数据进行清洗,并且限制输出前5条。执行结果为:

飞书推送

使用webhook来实现飞书的推送。获取webhook的步骤为:

  1. 创建飞书群组

2、配置机器人

3、获取webhook地址

经过上面步骤,就可以获得飞书的webhook地址啦。然后在n8n的工作流中,加入http request节点。对应配置如下:

最后这一步,body主要是为了设置在飞书群组里面,推送的内容样式。例如下面的样式一:

样式二:

不同的推送样式,主要是在body里面,通过JSON代码来修改。分享下我的代码,为:

{ "msg_type": "interactive", "card": { "config": { "wide_screen_mode": true }, "header": { "title": { "tag": "plain_text", "content": "RSS新闻推送" }, "subtitle": { "tag": "plain_text", "content": "最新资讯更新" } }, "elements": [ { "tag": "div", "text": { "tag": "lark_md", "content": "**{{ ($json.title || '无标题').replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim() }}**" } }, { "tag": "div", "text": { "tag": "lark_md", "content": "🕒 发布时间:{{ $json.pubDate || '未知时间' }}\n📡 来源:RSS订阅\n\n🔗 [点击查看原文]({{ ($json.link || 'https://36kr.com').replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim() }})" } }, { "tag": "button", "text": { "tag": "plain_text", "content": "打开原文链接" }, "type": "primary", "url": "{{ ($json.link || 'https://36kr.com').replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim() }}" } ] } }

最终,点击execute 就可以执行整个工作流啦

http://www.jsqmd.com/news/971974/

相关文章:

  • 告别手动操作!教你用批处理(.bat)和VBS脚本打造一键重启Windows资源管理器工具
  • 告别‘细节模糊’:用BiSeNet V2的‘双边网络’思路,在移动端也能玩转高精度实时语义分割
  • 为Unitree Go1机器狗部署PaddlePaddle:从环境准备到Camera SDK调用实战
  • 别再乱定义变量了!汇川InoProShop全局变量类型详解(含掉电保持设置)
  • 在Ubuntu 18.04上,用阿里源搞定东山Pi壹号开发板的SDK编译环境(保姆级避坑)
  • 在联盛德HLK-W806上玩转单色LCD:用ST7567自制一个极简天气站(附开源代码)
  • Weka数据预处理实战:用‘Discretize’滤波器一键搞定连续数据分箱,让模型更稳定
  • 清洁度分析仪哪个厂家有战略合作?西恩士工业怎么样 - mypinpai
  • SAP WM实战:手把手教你追踪一个仓储单位(SU)的完整生命周期(从收货到清空)
  • 告别官方SDK的坑:用iosetting大佬的wm-sdk-w806,手把手教你搭建W806开发环境(附CDK配置)
  • Android音频框架源码解析:audio_policy_configuration.xml是如何被Serializer.cpp优雅解析的
  • 别再为HC-42蓝牙模块AT模式发愁了!一个Arduino Uno + 手机App的保姆级配置指南
  • 用STM32CubeMX+Keil5快速配置RZ7886电机驱动(附完整代码包)
  • Nginx黑白名单进阶玩法:从手动配置到结合Lua+Redis的动态封禁(防爬虫/CC攻击实战)
  • 手把手教你用RT-Thread点亮CH32V307开发板的LED灯(附完整代码)
  • 【分享】VideoGuru视频编辑 裁剪拼接,合并调速 解锁会员
  • 2026年北京格局装饰装修性价比排行榜,如何选择? - 工业品牌热点
  • 告别手动采样!用ArcGIS的‘创建随机点’和‘按点提取值’工具高效完成生态调查数据分析
  • AD9361接收功能验证避坑指南:从官方配置软件到SPI寄存器,手把手教你搞定LVDS数据接收
  • 手把手教你用TTL线刷电信IHO-3000高安版机顶盒(附免费固件包)
  • 别只盯着任务创建了!用STM32CubeMX玩转FreeRTOS的任务状态机(挂起、恢复、删除)
  • 别再每次烧录了!用STM32F4内部Flash保存PID参数,一个实用技巧搞定
  • 手把手教你用CANdb++ Editor创建DBC文件(附信号、报文、节点完整配置流程与避坑点)
  • 手把手解读:用Python代码实战计算知识图谱的MRR、Hits@1和Hits@10
  • 可自定义报告的清洁度分析仪推荐 - 工业品牌热点
  • 飞思卡尔FRDM-KL25Z开发板入门:除了点灯,用状态机设计游戏才是正解
  • Lombok的@Log家族成员太多挑花眼?一篇讲清@Slf4j、@Log4j2、@CommonsLog到底怎么选
  • 航模DIY必备:SBUS信号转USB模块的硬件选型与自制教程(从原理图到外壳)
  • 从开发者视角看Flask SSTI:如何安全地设计模板与避免常见的‘可控变量’陷阱
  • 北京靠谱离婚律师推荐:首推股权与查账专家高静 - 本地品牌推荐