📕基于 RSS 的阅读分流器

type
status
date
slug
summary
tags
category
icon
password
author
标签
第三方接入
这是一个我在实际使用中的 Workflow,它的功能是,将光明日报每日头几版的内容,按照“综述”、“评论”、“文件”、“其他”四个分类进行分拣,然后存入 Google Sheets 中。
你可以在这个 Workflow 中学习到:
  1. 如何从 RSS 获取信息;
  1. 如何根据时间进行筛选;
  1. 如何通过 HTTP Request 获取网页全文;
  1. 如何通过大模型进行文章分拣;
  1. 如何从非结构化文本中提取数据;
  1. 如何将数据写入 Google Sheets;

1. Worlflow 预览:

notion image
下面的部分,我们将按照 Workflow 的工作顺序,来解释每一个节点都在做什么。

2. Workflow 详解:

第一步 RSS Read - 获取全部文章

这个节点是 n8n 的一个官方节点,它的作用是从指定的 RSS 地址获取数据。这不是一个 Trigger 节点,意味着它不会在 RSS 更新的时候自动触发 Workflow。
与之对应的是 RSS Trigger 节点,会在 RSS 地址更新后自动触发 Workflow。
两者的区别如下:
RSS Trigger
RSS Read
会触发 Workflow
不会触发 Workflow
仅获取 RSS 更新的部分
每次都会获取 RSS 输出的所有内容
你可以根据自己的需求选择,我在这里选择 RSS Read 是因为我选择的光明日报 RSS 是一个每日在指定时间点批量更新的订阅源。
因此,我将这个 Workflow 设置为手动触发,然后用另一个定时任务在每天指定时间触发这个 Workflow,通过 RSS Read 作为第一个节点获取 RSS 内容。 在这里,我不用 RSS Trigger 的原因是,在这种一次更新数十条的订阅源下。如果使用 RSS Trigger 作为启动器,它会在 RSS 更新的瞬间同时将 Workflow 运行数十次,引起服务器负载过高。
但使用 RSS Read 将最新的数十条内容一次读取,后续进行批处理,就不会有问题。
notion image
RSS Read 节点选项很少,你只要填入 RSS 地址即可。它的 OUTPUT 结构与 RSS 输出的结构完全相同。

第二步:Filter - 过滤非今天的文章

经过阅读 RSS Read 输入的内容我们发现,这个 RSS 输出的文章是会跨越日期的。也就是说,它不止会给出今天的文章,还会有昨天,可能还有前天的。
我们要实现的目标是,将每日的新文章存入一个表格,因此我们需要一个 Filter 节点来过滤掉以前的文章。
notion image
在 Filter 节点中,你可以通过 Add Condition 来添加过滤条件。我们可以看到,在这里我添加了一个条件。
这个条件是:
这个过程你是不需要太写代码的,在 n8n 的节点编辑界面,你可以将历史数据直接拖拽进文本框。在这里,我就是直接从这里拖进文本框的:
notion image
{{ $today }} 是一个 JS 代码,它代表今天的日期,会根据你每次运行 Workflow 的时间变动。在 n8n 中,文本框处于 Expression 模式时,你可以使用 {{ code }} 来插入 JS 代码。
与之对应的是 Fixed。在 Fixed 模式下,文本框里的内容将被完全视为文本,不做任何之行。
我们可以从输出看到,经过这个条件执行中,OUTPUT 面板里丢弃了 4 条结果,保留了 56 条结果。证明我们此次运行时,RSS 原本里包含了 4 条昨天的新闻。

第三步:Filter 1 - 过滤不想要的版面

光明日报是一份很厚的报纸,但我日常只需要关注它的前几版,在我们使用的这个 RSS 地址里,它会将文章所处的报纸版面写进文章标题里。因此,我们需要再来一个 Filter 节点,过滤数据中不属于头几版的内容:
notion image
在这里,我添加了三个条件,他们之间用 or 的逻辑来链接。这意味着,只要文章标题中包含“头版”、“要闻”或“评论”的任意一个词,Filter 就会将它保留下来,剩下的丢弃。
到这一步,我们在 OUTPUT 面板中保留了 20 个数据,丢弃了 36 个数据。

第四步:Filter 2 - 过滤不想要的报道类型

光明日报还是一个内容丰富的报纸,它经常会有一些我不太关心的内容,比如文艺评论,比如图片摄影等等,我们还需要从文章中剔除这些类型。幸好,在我们使用的这个 RSS 地址里,它也会把报道类型写在标题里,于是,我就又添加了一个 Filter,它的配置如下:
notion image
这已经是你第三次见到 Filter 节点了,我相信你已经可以从这张截图中理解我做了什么。

第四步:HTTP Request - 获取网页全文

如果是一般的 RSS,其实可以跳过这一步,包括这个光明日报的 RSS,它其实也在 RSS 里包含了文章全文。
但遗憾的是,这个 RSS 不包括作者,而我们想要对文章精准的分类,需要能知道文章的作者是谁。这时,我们就需要用 HTTP Request 节点,来帮助我们获取原始文章页面,并从 HTML 中提取作者:
notion image
HTTP Request 节点的作用是发起 HTTP 请求,它的作用有很多,但基础用法就是从一个 URL 中获得数据。在这种基础用法中,我们要选择它的 Method 为 Get。
然后,在 URL 参数中填入从 RSS 数据里活的的文章原始链接变量,这个节点的设置就完成了。
我们可以在 OUTPUT 中看到,与RSS 的结构化数据不同,我们发现它输出的是一个平文本,该文本就是 URL 所返回的网页 HTML 原文。
让我们进入下一步对 HTML 进行处理。

第五步:从 HTML 中抽取作者

经过手工阅读 HTML,我们会发现在光明日报的网页上,它会在一个隐藏的地方标记文章作者,它被包裹在<founder-author>的 HTML 标签里:
为了能够从每个页面的该标签中提取作者,我们需要使用 n8n 的 Code 节点。该节点用于实现那些 n8n 预设节点中不能实现的功能,它可以让你自己便携 JavaScript 或 Python 代码并运行。
我当然是不会写 JavaScript,因此我将问题抛给了 ChatGPT,我对它说:
我正在撰写一个 n8n 的 Workflow,需要从一个 HTML 网页中提取文章作者。文章作者被包裹在<founder-author>的 HTML 标签内。请帮我编写放在 Code 节点中的 JavaScript 代码,实现这一步骤。
ChatGPT 一般会给出详尽的指导,并给出代码:
可以看到,ChatGPT 生成的代码假定上一个节点是 RSS Feed Trigger,这与实际情况不符,所以我需要将其修改为:
然后进行测试运行,发现 Code 节点顺利运行,输出了所有有作者文章的作者:
notion image

第六步:Switch - 用硬规则分流

我们发现,所有官媒的“综述”这个类型的文章,都会在标题中包含“综述”二字。
因此,我们在对这类文章进行分类时,其实不用大语言模型参与。我们只需要用一个 if 或 Switch 节点就行了。这两个节点的区别:
Switch
If
可以进行多种结果的判断
只能进行两种结果的判断
判断结果可自定义变量,如“综述”、“非综述”
判断结果只会输出 True 或 False
在这一步,我们首先会发现上一步的 Code 输出里不带有此前的数据,因此在 Switch 节点的 Input 面板里没有文章标题了,这要怎么办呢?
notion image
我们可以在 INPUT 面板的标题处,选择之前的节点 Filter。这时,我们就可以和之前一样,拖拽我们想要的标题属性进入 Routing Rules 里做判断了。
这里我选择了从 Filter 里读取 title 属性来做判断。但如果你还记得,我们在 Filter 1 和 Filter 2 里丢弃了不少不符合我们需求的条目。
但在 n8n 中,整个工作流里的数据,遵循隐式行列传递,这意味着当数据流抵达下游节点时,仅会以上游 1 个步骤的节点输出的数据为准进行执行。
notion image
仍以本例做说明,Filter 节点里有 56 个条目,运行到 Switch 时,已经只剩 19 个条目了。此时,我从 Filter 里读取 title,它只会读取剩下的这 19 个条目的 title,不会把被丢弃的 37 个条目找回来。
并且,这 19 个条目的标题也是行列对齐的,你不用在意中间丢弃的是哪些行去做手工的对齐。

第七步:Basic LLM Chain - 使用大模型进行文章分拣

接下来,我们开始接入 AI 了。
n8n 中内置了 LangChain 节点,它被称为 Advance AI,它能实现很多功能,在本例中我们使用的是最简单的功能,因此,我们要添加的是一个 Basic LLM Chain。这个节点顾名思义,就是最基础的接入大语言模型的节点。
notion image
这个节点的配置非常简单,它只有两个主要选项,一个是 Prompt 一个是 Text。
Prompt 有两个选项,一个是 Define below(在下方定义),一个是 Take from previous node automatically(从之前的节点获取)。在这里,我们要选择 Define below,这样 Text 参数就会出现。我在 Text 中填入了以下 Prompt:
这段 Prompt 的作用顾名思义,前面是判断规则,最后通过 Javascripts 变量,引入每篇文章的标题、作者和正文。
如果你希望用来判断其他内容,自己去做 Prompt 调整就行。
n8n 的所有 AI 节点与一般节点不同,还至少需要一个额外的子节点来完成配置,也就是你需要选一个具体的模型。在这里,我给它挂上了 Google Gemini Chat Model(因为免费):
notion image
在子节点中,我们需要对模型进行单独的设置,首先是 Credential(凭据),也就是你自己的 Google Gemini API Key,这里不会教你如何申请,你可以自己去搜一下。
然后第二个是 Model 选项,在你配置完 Credential 后,它会自动刷新你可使用的模型版本,我这里选择了免费量大的 gemini-1.5-flashlatest。
根据 Google 对模型的定义,该模型还支持设置 Safety Settings,也就是 API 对一些敏感内容的拦截阈值,我们全都拉到完全不拦截,这个节点就完成啦:
notion image
试运行一下,它的生成过程较慢,在运行的过程中编辑器里会显示目前处理到第几条数据,你应该会在 OUTPUT 看到一列输出文章类型的数据:
notion image

第八步:Google Sheets - 写入数据库

其实到此为止,我们已经完成了文章分类筛选的工作,但是为了方便我们获取分拣结果,我们一般还是要把它导入到一个数据库里的,比如 notion,比如 Excel。
在这里,我选择了我常用的 Google Sheets,也就是 Google 的在线表格:
notion image
我们首先添加一个 Google Sheets 节点,还是先添加 Google Sheets 的 Credential,这个过程略去(你可以参考 n8n 官方节点)。
然后 Resource 选 Sheets Within Document。
Operation 选择 Append Row(添加行)。
Document 这里选择贴 By URL,然后去你的 Google Sheets 中将预先建立好的用于存储数据的表格地址复制过来贴到这里。
在贴完地址之后,你应该会在 Sheet 里看到对 Sheet 的选择(和 Excel 一样,每个工作簿有多个表格,你要选一个)。
最后,在 Mapping Column Mode 这里选择 Map Each Column Manually(手工映射列)。
到这里,如果一切正常,你可以在下方找到一个 Add Column to Send 的按钮,点击之后,它会列出表格里所有已经有的表头:
notion image
点击之后,就会在 Values to Send 里添加一个可以映射的配对:
notion image
这个时候,你就按照之前的思路,将各个变量拖进去就可以啦。我的表格里有这些列,它们在工作流里对应的变量分别是这样的:
Sheets 里的列
工作流里的变量
解释
标题
{{ $('Filter1').item.json.title }}
从 Filter1 节点读取的标题
URL
{{ $('Filter1').item.json.link }}
从 Filter1 节点读取的原文地址
日期
{{ $('Filter1').item.json.pubDate.toDateTime().format('yyyy-MM-dd') }}
从 Filter1 节点读取的日期,进行日期格式化为“年-月-日”
来源
光明日报要闻
写死的“光明日报来源”
分类
{{ $('Basic LLM Chain').item.json.text.replace(/\s+/g, '') }}
从 Basic LLM Chain 读取的文章分类,去除 AI 可能输出的换行符
还记得吗?我们在第六步用 Switch 节点硬筛选了“综述”类文章,这意味着,你要在那里也添加一个 Google Sheets 节点,然后同样的配置。
如果一切顺利的话,回到 Google Sheets,你会发现文章已经被成功分拣完成啦~
notion image

3. 示例 Workflow 下载

你可以通过在 n8n 中新建一个 Workflow 然后选择右上角的 Import from File 来导入这个示例 Workflow。但需要注意的是,它无法自动执行,你需要重新配置 Google Gemini 的凭据和 Google Sheets 的凭据才能使用。

4. 发散

分拣光明日报总体来说可能是一个十分小众的场景,在实际使用过程中,你可以参考这个 Workflow 的思路拿来分拣其他 RSS。
当然,如果你可以使用 Inoreader 或 FressRSS 等支持聚合的 RSS 阅读器,你可以将你所有订阅的 RSS,在这些阅读器中聚合成一个 Feed,然后将所有文章都通过这个 Workflow 进行一遍过滤分拣。
通过变换 Switch 或 Filter 节点的规则,你可以删除 RSS 里那些短效的内容(比如快讯)。通过变换 AI Node 里的 Prompt,你可以对更多内容进行分拣,比如技术相关、文学相关、历史相关、旅游相关等。
通过变换最终的数据库,你还可以将筛选后的内容存入 notion 或 obsidian,甚至直接再接一个 AI Node 来生成网页格式的每日简报。
总之,本文提供了一个从 RSS 获取数据,通过逻辑节点和 AI 节点进行信息分类,再存入数据库的一般思路。至于能用到什么场景中,那就需要你自己发挥想象力啦~
广告
n8n内建变量与方法获取中国哪些县城有麦当劳
Loading...
目录