1. 前言

在 AI 兴起之后,很多这类服务都快速添加了调用 OpenAI API 的功能。但是它们有一个共同的缺点就是太贵了。可以对比一下此类产品的价格:

产品 价格
Zapier 免费用户每月 100 次任务。最低升级价格 $20/月,含 750 次任务
IFTTT 免费用户可保存 3 个自动化(Applets)。含有 AI 功能的升级方案升级 $5/月
集简云 免费用户每月 500 次执行。升级一年 ¥1990,每月可执行 1500 次
HiFlow(腾讯轻联) 免费用户每月 1000 次执行。升级一年 ¥980,每月 3000 次

n8n 是一个开源的自动化控制台。它具有设计简洁的图形界面,可以非常清晰地展示数据在各种服务之间流动的过程。对于入门用户,n8n 提供了丰富的模板,也有活跃的社区支持。

n8n 提供官方托管服务,定价也不便宜。但得益于开源属性,可以比较方便地在自己的 NAS 或 VPS 上部署,从而不需要任何额外开销。

1.1. Docker Compose 安装 n8n

n8n 的安装方式有多种选择, Docker Compose 是一种比较容易上手的方案。

# clone n8n source code
git clone https://github.com/n8n-io/n8n.git
# go to docker-compose directory
cd n8n/docker/compose/withPostgres
docker-compose up -d
  • .env: (必选)打开后根据提示编辑其中的三处用户名和密码。前两组用于数据库,最后一组用于浏览器登录使用。
  • docker-compose.yml:(可选)打开编辑 n8n 相关设置,如果有域名,这里可以绑定域名,在 services.n8n.environment 部分添加 - N8N_HOST="[domain name or IP]"  即可;如果有更换端口的需求也可以自行更改。
  • README.md、init-data.sh:维持原样不动。

访问 [服务器域名 or IP]:5678 时,即可使用刚刚在 .env 中编辑的最后一组登录密码进入管理页面。

2. n8n 的基本使用

n8n 的管理页面非常简洁,左侧分别为:

  • Workflows:创建和管理自动化流程
  • Templates:社区已有的一些模板,可以直接查找使用
  • Credentials:管理第三方服务的登录验证信息
  • All executions:已经执行过的日志记录

在 Workflows 页面选择 Add Workflow,就可以创建新的工作流程了。

2.1. Workflow 中最重要的两个元素——触发器和节点。

触发器(trigger)是一个 Workflow 中的起点,设定的条件满足后,就会执行后续的流程。一个 Workflow 中可以有多个触发器。

新建一个 Workflow 之后,第一步就会要求添加一个「起点」,这个起点就是触发器。

触发器的类型有如下几种:

  • On app event:由第三方应用中的事件触发。
  • On a schedule:定时触发。
  • On webhook call:通过 webhook 触发,即在其他应用中向 n8n 发送 HTTP 请求 触发。
  • Manually:手动点击按钮触发。
  • When called by another workflow:通过其他 Workflow 的调用触发。
  • 其他场景:针对文件变更、报错等特殊场景。

触发器的后续步骤都是节点(node),即根据流程需要依次执行的指令。

节点的类型非常多样,可以自己根据 n8n 的文档(可以通过每个节点设置中的 Docs 标签,或者一些待填项目右侧的问号按钮访问)摸索。

首先,HTTP Request 节点用于发送请求,设置内容是很标准的方法、URL、鉴权方式和请求内容等。这里有个很方便的 Import cURL 按钮。因为很多 API 文档里都会提供 cURL 命令格式的示例,浏览器开发者工具也支持直接复制 cURL 命令格式的请求,用这个按钮就可以自动将其参数填写到对应的设置项中,不用自己一一手动操作了。

其次是 Execute Command 节点,可以直接执行 Shell Script,是最常用的节点。

除此之外,n8n 也内置了丰富的控制流节点(如分支和循环)、第三方应用节点等,这与商业化服务类似,不再赘述。

3. 实例演示:从滴答清单到 Notion

作为一个本土软件,滴答清单在海外为主的自动化平台中受支持比较少,n8n 也没有专门支持。好消息是,滴答清单的 API 比较开放,理论上可以纯靠发送 HTTP 请求实现各项功能。坏消息是,滴答清单官方 API 文档显然有些过时了,跟着操作无法正常读取信息和任务列表。

为此,我想到一个取巧的办法:在 Github 上搜索 Dida365 和 API,抄抄别人的作业。这一搜果然有收获,通过阅读别人的代码,我发现先通过用户名和密码登录,获取 Cookies,就可以登录并操作网页版滴答清单,实现任务的搜索和编辑了。

3.1. 滴答清单配置

3.1.1. 定期获取 Cookies

首先设置了一个专门用于登录的 Workflow。由于登录一次之后,Cookie 可以保存一段时间,所以我们可以利用这种机制减少登录频率,减少被认为是不合理使用的风险。

 

这里,第一个节点是定时触发器,每天早上 8 点会触发这个工作流,刷新一次 Cookies 并存储下来,供后续其他 Workflow 使用。

上图中,0 8  * * * 是 Crontab 格式表达的「每天八点」。

3.1.2. 添加一个 HTTP 节点用于登录。

API 和 header 的信息按照上图进行设置。用到的部分固定参数如下(来源于从浏览器开发者工具测试并导出请求):

然后打开 Send Body,在其中设置内容类型为 JSON。添加两个名称分别为 username 和 password 的参数,值分别为滴答清单的用户名(手机号码或者邮箱)和密码。

3.1.3. 简单测试

n8n 中的每一个节点都有 Execute node 按钮,点击可以单独执行这个节点进行调试。

测试结果可以用表格或者 JSON 的形式输出。

上图中,我们看到节点成功获取了登录 token。

3.1.4. 获取 token

如何让其他的 Workflow 使用这里的 token 呢?这里就需要使用 n8n 特殊的设计:Execute Command 节点,这也是它比其他很多服务更灵活强大之处。

本质上,Execute Command 的功能是在 n8n 的运行环境(这里是我们的 Docker 容器)中运行给定的 Shell 脚本。这里的 Shell 脚本可以直接访问运行环境的各个目录,例如 Linux 的通用临时文件路径 /tmp。我们可以将各种变量写入 /tmp 目录的文件中,从而作为「全局变量」在各个 Workflow 中进行使用。

为此,我新建一个叫做 store token 的 Execute Command 节点,串接在之前的 Dida login 节点之后。打开其设置,将 Command 设置项右侧的类型从 Fixed 改为 Expression(区别在于是否支持使用变量),然后填入如下命令:

echo  {{ $json.token }} > /tmp/token.txt

这里,{{ $json.token }} 是 n8n 嵌入数据等变量的格式,指从(输入节点的)JSON 输出中提取 token 键的值(完整语法可以参考文档)。不过,大多数时候并不需要手动输入,只要将之前测试所得结果中的所需字段直接拖拽到输入框里就行了。

这样就将 token 存入了 /tmp/token.txt 文件中。其他 Workflow 需要使用的时候,使用 Execute Command 节点去读取该文件的内容就可以访问了。

3.2. 连接 Notion

n8n 内置了 Notion 节点,只要绑定自己的 Notion 账户就能使用。为此,打开自己 Notion 账户的 My integrations 页面,添加新的 integration(可以根据自己的需求编辑一个较窄的权限范围,提高安全性),然后复制所得的 token。

之后不要忘记在需要编辑的 Notion 页面中添加这个新 integration:


回到 n8n,在 Notion 节点中选择 Create New Credential,粘贴上述 token。

3.2.1. 创建 Notion 页面节点

创建一个新页面,并添加了一个 Daily Report 的 H1 级别标题。

3.2.2. 存储页面 ID

这效仿之前步骤中的思路,将 Notion 的页面 ID 存储下来,方便后续调用。

echo  {{ $json.id }} > /tmp/lastid.txt

 

3.2.3. 获取滴答清单 token

用 cat 命令获取了之前滴答清单步骤记录下在 /tmp 目录中的 token 信息。

3.2.4. 获取当日任务列表

从滴答清单中获取了当日任务列表,其中的查询范围是用 n8n 的内置时间变量组合成的 ISO 8601 格式。

  • URL: https://api.dida365.com/api/v2/project/all/completed
  • from: {{ $now.minus({days:1}).setZone('Asia/Shanghai').toISO().slice(0, 11).replace(/-/g, "-").replace("T", " ") + "00:00:00"}}
  • to:  {{ $now.minus({days:1}).setZone('Asia/Shanghai').toISO().slice(0, 11).replace(/-/g, "-").replace("T", " ") + "23:59:59"}}
  • limit: 50

Header 部分需要将之前取到的 token 写入 cookie 中,用于鉴权,配置方式如下。这里,用到了 $node["节点名"] 表达式,获取特定节点的输出。

3.2.5. Split in Batch 节点

这个节点可以将刚刚获取的一串数据依次送入下一个节点。Batch Size 输入 1,每次只向 Notion 页面中写入一个任务的信息。

 

3.2.6. 获取 Notion 页面 ID

将刚刚的 Notion 页面 id 取回:

cat /tmp/lastid.txt

3.2.7. 任务信息写入 Notion 页面

这里使用了多个节点的信息,拖动输入不太方便了,而且有些 bug,建议手动编辑:

  • Block: {{ $node["Fetch Last ID"].json.stdout }}
  • Task Text: {{ $node["Split In Batches"].json.title }}

页面串接好并启用之后,每天的 8 点,在上班的时候就能看到我前一天的任务日报了

  • 无标签
写评论...