使用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语言,对应的代码如下:

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代码,对应代码如下:

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代码来修改。分享下我的代码,为:

javascript 复制代码
{
  "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 就可以执行整个工作流啦

相关推荐
拾年2751 小时前
从零手写 Ajax:用原生 XHR 搭建前后端交互全流程
前端·javascript·ajax
拉勾科研工作室2 小时前
区块链工程毕业论文题目【249个】
开发语言·javascript
小林ixn2 小时前
你以为你懂 + 号?看完这篇 Bun + TS 实战,才发现以前全写错了
前端·javascript·typescript
jvxiao3 小时前
你真的懂作用域吗?从编译原理角度深度 JS 的作用域
前端·javascript
Darling噜啦啦3 小时前
二叉树与递归算法实战:从树结构到 LeetCode 爬楼梯,一文吃透前端数据结构与递归思维
前端·javascript·数据结构
x-cmd3 小时前
[260612] x-cmd v0.9.8:x feishu 发送消息支持 Markdown + 卡片,让 x claw 接入飞书后消息不再干巴巴
飞书·agent·claude·命令行·x-cmd·openclaw
诗词在线4 小时前
专业的飞花令网站
飞书
Sammyyyyy4 小时前
月之暗面 Kimi Code 0.4.0 发布,终端 AI 编码助手全面采用 TypeScript,实现毫秒级启动
前端·javascript·人工智能·ai·typescript·servbay
宋拾壹5 小时前
fastadmin列表中查看列表,并且添加增加相应的数据
javascript·php·fastadmin
云水一下6 小时前
Vue.js从零到精通系列(三):组件化基础——Props、Emits、插槽与生命周期
前端·javascript·vue.js