n8n搭数字员工:每日自动推送选题消息卡片

前两篇咱们聊了怎么用 n8n 监控 YouTube 和 B 站,把更新情报自动“抓”进飞书多维表格。

【链接】xiaobot:https://xiaobot.net/post/e6cb9f6d-acc9-4dbd-bdec-d874bada06ae

配图

随着表格中的数据越来越多,又出现了一个新的问题:“抓是抓进去了,但是没空看”。确实,每天表格里躺着上百条数据,还得点开表格去扫哪些数据是当天更新的,稍微还是有点麻烦。

所以我在想,能否“每天早上 8 点,用飞书给我推一条消息,把前一天更新的内容汇总给我,如果我对某一条更新感兴趣,就点一下加入选题库,把它收藏到多维表格里”

类似这样一个汇总卡片提醒。

配图

这样的好处是,从你主动要去表格人肉查看数据,变成机器人主动汇总并推送给你。今天就来讲讲,如何实现这样一个汇总+推送+入库的自动化工作流。

一、 前期准备

1、情报内容多维表格

首先要有一个数据源,汇总你所有的情报内容。这个在之前的文章有讲过,通过n8n工作流自动获取并写入到多维表格中。接下来是要从这张表里筛出前一天更新的数据并汇总。

配图

2、自动汇总的工作流

每天早上8点,需要这个工作流自动运行,去情报内容多维表格翻翻昨天谁更新了,然后汇总并通过飞书机器人发送给我。

这个工作流我们还是用n8n来实现。

3、写入选题库多维表格的工作流

收到卡片消息,如果你对某一条感兴趣,想保存下来以后做参考,就点击卡片的加入选题库按钮,把这一条内容写入到选题库多维表格里。

配图

配图

这个工作流,我们也用n8n来实现。

接下来我们就讲讲这两个工作流如何配置。

二、 情报汇总推送工作流

这个流程的目标是:去昨天的记录里“捞人”,拼成卡片发出去。

这个流程是主动干活的。每天早上 8 点,它去多维表格里翻翻昨天谁更新了,然后拼成卡片发送给我。

配图

节点 1:定时触发 (Schedule)

开始节点,设定每天 08:00 运行。你也可以根据实际需要,修改流程自动触发的时间。

节点 2:获取飞书 Token

调用 tenant_access_token 接口。可以理解这是所有后续操作的“工牌”,没它进不去飞书的大门。

这个配置之前也写过很多次了,这里就不详细说明了。

节点 3:初始化日期

用一段简单的 JS 代码算出“昨天”的日期字符串(如 2026-01-24),一会儿查表时要根据这个日期做过滤。

因为我们希望是在情报表里,根据发布时间,来筛选出昨天更新的内容。但是工作流自己是不知道昨天是哪一天的,这就需要我们在节点里自己获取。

function pad2(n) { return String(n).padStart(2, '0'); }

const now = new Date();
const shNow = new Date(now.toLocaleString('en-US', { timeZone: 'Asia/Shanghai' }));
shNow.setHours(0, 0, 0, 0);

const y = new Date(shNow);
y.setDate(y.getDate() - 1);

const yyyy = y.getFullYear();
const mm = pad2(y.getMonth() + 1);
const dd = pad2(y.getDate());

const dateStr = `${yyyy}-${mm}-${dd}`; 
const displayDate = `${parseInt(mm, 10)}月${parseInt(dd, 10)}日`;

return {
  dateStr,
  displayDate
};

运行后,会输出昨天的日期

配图

节点 4:分页查询

配图

为什么需要这几个节点?

因为我们调用飞书多维表格查询记录的接口,官方文档中说明单次最多查询 500 行记录,如果超过了,就需要分页获取,所以我们就需要遵循官方的要求。

配图

1、分页查询接口

调用飞书多维表格查询记录接口(https://open.feishu.cn/document/docs/bitable-v1/app-table-record/search?appId=cli_a6e243e0f9d9100c)

配图

配置字段如下:

(1)Method:post

(2)URL:https://open.feishu.cn/open-apis/bitable/v1/apps/[替换成你的表格token]/tables/[替换成你的表格table-id]/records/search

(3)Headers

①Authorization:{{ ‘Bearer ‘ + \$node[“获取Token”].json.tenant_access_token }}

②Content-Type:application/json; charset=utf-8

(4)body

json格式

{
  "view_id": "[替换成你的表格视图id]",
  "filter": {
    "conjunction": "and",
    "conditions": [
      {
        "field_name": "published_at",
        "operator": "contains",
        "value": [
          "{{ $node['初始化参数与日期'].json.dateStr }}"
        ]
      }
    ]
  },
  "page_size": 500,
  "page_token": "{{ $('处理分页与汇总').isExecuted ? $('处理分页与汇总').json.next_page_token : '' }}"
}

里面的”conditions”,就是过滤条件,根据published_at 字段 contains 我们算好的昨天日期。

2、处理分页与汇总

code节点处理逻辑

const data = $node["分页查询接口"].json?.data || {};
const items = data.items || [];

let all = [];
if ($('处理分页与汇总').isExecuted) {
  all = $('处理分页与汇总').json.all_records.concat(items);
} else {
  all = items;
}

return {
  all_records: all,
  has_more: !!data.has_more,
  next_page_token: data.page_token || ""
};

3、是否还有下一页

if节点,判断是否还有下一页, 如果没有了,就进行下一步操作,如果还有,就继续调用查询接口。

配图

节点 5:是否有记录 (If)

配图

防止“空跑”。如果昨天所有博主都没更新,后面构建卡片就会报 undefined 错误。

所以我们就在这里判断 all_records.length 是否大于 0。如果是True,则继续去发卡片。如果是False,就发一条“昨天暂无更新”的文本。

节点 6:汇总构建卡片 (Code)

这个节点,就是要把我们查询到的信息,拼成一张飞书卡片。

这一步其实是比较麻烦的,可能会需要一点代码基础。如果你不会,没事,问AI也行。

简单来说,飞书的卡片,其实就是一串json,我们构建这个卡片,就要遵循飞书官方的json格式要求。

官方说明:https://open.feishu.cn/document/feishu-cards/card-json-v2-structure

我们就需要把获取到的字段信息,塞到json里。

这个节点就是用一段js,来加工成我们需要的卡片格式。

const getText = (val) => {
  if (!val) return '暂无';
  let result = '';
  if (Array.isArray(val)) {
    result = val.map(v => v.text || '').join('');
  } else if (typeof val === 'object') {
    result = val.text || val.link || JSON.stringify(val);
  } else {
    result = String(val);
  }
  return result.trim();
};

const clean = (text) => {
  if (!text) return '暂无';
  return text
    .replace(/\*/g, '') 
    .trim();
};

const records = $node["处理分页与汇总"].json.all_records || [];
const displayDate = $node["初始化参数与日期"].json.displayDate;

let elements = [];

records.forEach((record, index) => {
  const f = record.fields;

  const author = clean(getText(f.author));
  const title = clean(getText(f.title));
  const summary = clean(getText(f.summary));
  const url = getText(f.url);

  elements.push({
    "tag": "div",
    "text": {
      "tag": "lark_md",
      "content": `第 ${index + 1} 条更新\n作者:${author}\n标题:${title}\n摘要:${summary}\n链接:[点击查看视频](${url})`,
      // 核心改动:设置 lines 为 0,表示不限制行数,全文换行展示
      "lines": 0
    },
    "extra": {
      "tag": "button",
      "text": { "tag": "plain_text", "content": "加入选题库" },
      "type": "primary",
      "value": { 
        "title": title,
        "author": author,
        "url": url,
        "summary": summary
      }
    }
  });

  if (index < records.length - 1) {
    elements.push({ "tag": "hr" });
  }
});

return { 
  card: {
    "schema": "2.0",
    "config": { 
      "width_mode": "fill" 
    },
    "header": {
      "title": { "tag": "plain_text", "content": `${displayDate} 选题监控` },
      "template": "blue"
    },
    "body": { 
      "elements": elements.slice(0, 100) 
    }
  } 
};

当执行之后,output出来的内容,就是飞书要求的卡片的json格式。

配图

在”加入选题库”的按钮里,我们在value字段里,把 多维表格里的title, author, url ,summary全塞进去。

如果觉得有困难,直接用AI来帮你写一块的逻辑,你只需要把飞书官方的指引文档丢给AI就好。多调试几次,就顺了。

节点 7:发送飞书推送 (HTTP Request)

最后,就是通过飞书机器人,来推送消息给我。

用HTTP节点,调用飞书发送消息的接口(https://open.feishu.cn/document/server-docs/im-v1/message/create?appId=cli_a6e243e0f9d9100c)

配图

(1)HTTP Method:post

(2)HTTP URL:https://open.feishu.cn/open-apis/im/v1/messages

(3)header:

①Authorization:{{ ‘Bearer ‘ + \$node[“获取Token”].json.tenant_access_token }}

②Content-Type:application/json; charset=utf-8

(4)Query参数

receive_id_type:open_id

(5)body

①receive_id:接收消息的人的openid

②msg_type:interactive (interactive意思是卡片类型的消息)

③content:{{ JSON.stringify(\$json.card) }},注意:必须用 JSON.stringify(\$json.card) 把上一步的对象转成字符串。

这个工作流就配置完成了。

当你运行后,就可以在飞书机器人收到这样的卡片消息。

配图

如果你只希望收到消息,到这一步就结束了,如果你还想在卡片上有一些交互。比如我点击卡片的加入选题库,就可以把对应的内容写到另一张多维表格选题库的表里。那么,我们就还需要配置接下来的这一条工作流。

三、 加入选题库工作流

这个流程是被动待命的,不像上一个流程会自动运行。一定要点击卡片上那个“加入选题库”的按钮,流程才会跑起来。

配图

这个工作流的开始节点是一个webhook节点,相当于你点击“加入选题库”,它就会收到一个“信息”,然后流程就会执行。

我们先看看怎么配置

节点 1:接收 Webhook (入口)

配图

这个节点有一个production url,我们要把这个url,配置到飞书开发后台的回调地址里(给你发送消息的飞书应用机器人的后台)

配图

节点 2:If节点

配图

飞书发来的请求分两类,一类是url_verification(飞书来查证件),另一类是真实的按钮点击数据。

配置:{{ \$json.body.type === ‘url_verification’ }}。

节点 3:返回Challenge验证码

配图

如果是类 A,直接用 Respond to Webhook 节点,把飞书发来的 challenge 原样还给它。这一步通了,飞书后台才能保存成功。

节点 4:写入多维表格

如果是类 B,调用飞书多维表格新增记录接口。

这个接口和第一个工作流的写入接口是同一个,只不过这个接口是写到我们选题库的多维表格里。

所以在url里,记得改下表格的id值

配图

body里,用json写明你要写入的数据值

{
  "fields": {
    "素材内容": "{{ $('接收飞书按钮点击').item.json.body.event.action.value.title}}",
    "url": "{{ $('接收飞书按钮点击').item.json.body.event.action.value.url }}",
    "summary": "{{ $('接收飞书按钮点击').json.body.event.action.value.summary }}",
    "author": "{{ $('接收飞书按钮点击').json.body.event.action.value.author }}"
  }
}

其他的配置都是一样。

这个工作流就配置完成了。

看到这一步可能你会有点懵,尤其是那个webhook,都不知道干啥的。

这个工作流配置确实不大好理解。

举一个例子:

  • 卡片按钮:类似一个“快递员”,他手里拿着你要加入选题库的数据。
  • 飞书后台:是“快递公司总部”。
  • n8n Webhook 地址:是你的“收货仓库”。

配置好之后:快递员一拿到货(点按钮),总部(飞书后台)立刻告诉他:“送到 n8n Webhook 这个仓库去!”快递员飞奔过去,你的 n8n 签收后立刻就开始搬砖(写入多维表格)。为什么要搞那个复杂的“Challenge 验证”?这就相当于快递公司总部(飞书)在发货前,先给你的仓库打个电话:“喂,我是飞书,我一会儿要给你送货,你能接吗?”你的 n8n 必须秒回:“能接,我是本人!”这就是所谓的安全握手,防的就是有人冒充你的仓库地址去偷数据。

还不太理解?没关系,可能需要一点点时间,找点这块的资料或者问问AI。

好了,以上就是这两个工作流的配置。

主要是把多维表格里的内容,汇总成飞书卡片消息,定时自动推送给我们,我们还可以在卡片点击按钮,把刚兴趣的内容保存到多维表格里。

五、 写在最后

为什么要花时间去搭建这样的工作流呢?因为虽然前期花时间,但流程一旦搭好,它就是一个 24 小时待命、永远不会累、永远按标准执行的“数字员工”。

这一套搭下来,我每天选题的时间至少能从 30 分钟缩短到了 10 分钟。剩下的 20分钟,我可以去深度思考怎么写好内容,而不是把精力耗费在“找链接”和“切表格”上。


📋 这套数字员工相关模板,我整理成模板了

跟着上面步骤搭要花点时间。想直接拿现成的改,加我微信备注「数字员工」,我发你。

🤔 卡在某一步了?

搭建过程里如果哪一步卡住了,如果你照着做没跑通,或者你们公司情况不太一样,可以找我聊聊,我免费帮你看看怎么调。不合适我也会直说。

加吨师傅微信咨询飞书多维表格搭建

扫码加我,备注「数字员工」领模板

想看更多这类方案,我都整理在 吨师傅工具箱 里了:客户管理、进销存、工单报修……按场景分好类,可以直接抄。

相关阅读

滚动至顶部