处理不同的数据类型#
在本章中,你将学习如何使用 n8n 核心节点处理不同类型的数据。
HTML 和 XML 数据#
你很可能熟悉 HTML 和 XML。
HTML vs. XML
HTML 是一种用于描述网页结构和语义的标记语言。XML 看起来与 HTML 类似,但标签名称不同,因为它们描述的是它们所持有的数据类型。
如果你需要在 n8n 工作流中 处理 HTML 或 XML 数据,请使用 HTML 节点或 XML 节点。
使用 HTML 节点通过引用 CSS 选择器来提取网页的 HTML 内容。如果你想从网站收集结构化信息(网页抓取),这非常有用。
HTML 练习#
让我们获取最新 n8n 博客文章的标题:
- 使用 HTTP Request 节点向 URL
https://blog.n8n.io/发出 GET 请求(此端点不需要身份验证)。 - 连接一个 HTML 节点并配置它以提取页面上第一篇博客文章的标题。
- 提示:如果你不熟悉 CSS 选择器或阅读 HTML,CSS 选择器
.post .item-title a应该会有所帮助!
- 提示:如果你不熟悉 CSS 选择器或阅读 HTML,CSS 选择器
显示解决方案
- 使用以下参数配置 HTTP Request 节点:
- Authentication(身份验证):None
- Request Method(请求方法):GET
- URL:https://blog.n8n.io/ 结果应如下所示:

HTTP Request 节点的结果
- 将 HTML 节点连接到 HTTP Request 节点并 配置前者的参数:
- Operation(操作):Extract HTML Content
- Source Data(源数据):JSON
- JSON Property(JSON 属性):data
- Extraction Values(提取值):
- Key(键):title
- CSS Selector(CSS 选择器):
.post .item-title a - Return Value(返回值):HTML
你可以添加更多值来提取更多数据。
结果应如下所示:

HTML Extract 节点的结果
使用 XML 节点将 XML 转换为 JSON,将 JSON 转换为 XML。如果你使用不同的 Web 服务,这些服务使用 XML 或 JSON,并且需要在两种格式之间获取和提交数据,则此操作非常有用。
XML 练习#
在第 1 章的最后练习中,你使用 HTTP Request 节点向 PokéAPI 发出请求。在本练习中,我们将返回到同一个 API,但我们将输出转换为 XML:
- 添加一个 HTTP Request 节点,向 PokéAPI 发出相同的请求,地址为
https://pokeapi.co/api/v2/pokemon。 - 使用 XML 节点将 JSON 输出转换为 XML。
显示解决方案
- 要从 PokéAPI 获取宝可梦,请使用以下 参数执行 HTTP Request 节点:
- Authentication(身份验证):None
- Request Method(请求方法):GET
- URL:https://pokeapi.co/api/v2/pokemon
- 将 XML 节点连接到它,并使用以下参数:
- Mode(模式):JSON to XML
- Property name(属性名称):data
结果应如下所示:

XML 节点(JSON 到 XML)– 表格视图
要以另一种方式转换数据,请选择模式 XML to JSON。
日期、时间和间隔数据#
日期和时间数据类型包括 DATE、TIME、DATETIME、TIMESTAMP 和 YEAR。日期和时间可以以不同的格式传递,例如:
DATE:March 29 2022、29-03-2022、2022/03/29TIME:08:30:00、8:30、20:30DATETIME:2022/03/29 08:30:00TIMESTAMP:1616108400(Unix 时间戳)、1616108400000(Unix 毫秒时间戳)YEAR:2022、22
你可以通过几种方式处 理日期和时间:
- 使用 Date & Time 节点将日期和时间数据转换为不同的格式并计算日期。
- 使用 Schedule Trigger 节点安排工作流在特定时间、间隔或持续时间运行。
有时,你可能需要暂停工作流执行。如果你知道某个服务不会立即处理数据或返回所有结果的速度很慢,这可能是必要的。在这些情况下,你不希望 n8n 将不完整的数据传递给下一个节点。
如果你遇到这样的情况,请在要延迟的节点之后使用 Wait 节点。Wait 节点暂停工作流执行,并将在以下情况下恢复执行:
- 在特定时间。
- 在指定的时间间隔之后。
- 在 webhook 调用时。
日期练习#
构建一个工作流,将你之前使用的 Customer Datastore 节点的输入日期加上五天。然后,如果计算的日期发生在 1959 年之后,工作流会在设置计算日期作为值之前等待 1 分钟。工作流应每 30 分钟触发一次。
开始:
- 添加 Customer Datastore (n8n training) 节点,选择 Get All People 操作。返回全部。
- 添加 Date & Time 节点,将数据存储中创 建的日期向上舍入到月末。将其输出到字段 new-date。包括所有输入字段。
- 添加 If 节点以检查新的舍入日期是否在
1960-01-01 00:00:00之后。 - 将 Wait 节点添加到该节点的 True 输出,并将其设置为等待一分钟。
- 添加 Edit Fields (Set) 节点以设置一个名为 outputValue 的新字段,该字段为包含 new-date 的字符串。包括所有输入字段。
- 在工作流开始时添加 Schedule Trigger 节点,以每 30 分钟触发一次。(你可以保留 Manual Trigger 节点进行测试!)
显示解决方案
- 添加 Customer Datastore (n8n training) 节点,选择 Get All People 操作。
- 选择 Return All(返回全部)选项。
- 添加连接到 Customer Datastore 节点的 Date & Time 节点。选择 Round a Date(舍入日期)选项。
- 添加
created日期作为要舍入的 Date(日期)。 - 选择
Round Up(向上舍入)作为 Mode(模式),选择End of Month(月末)作为 To(到)。 - 将 Output Field Name(输出字段名称)设置为
new-date。 - 在 Options(选项)中,选择 Add Option(添加选项)并使用控件 Include Input Fields(包括输入字段)
- 添加
- 添加连接到 Date & Time 节点的 If 节点。
- 添加 new-date 字段作为条件的第一部分。
- 将比较设置为 Date &Time > is after(日期和时间 > 晚于)
- 添加
1960-01-01 00:00:00作为表达式的第二部分。(这应该在 True 分支中产生 3 个项目,在 False 分支中产生 2 个项目)
- 将 Wait 节点添加到 If 节点的 True 输出。
- 将 Resume(恢复)设置为
After Time interval(时间间隔后)。 - 将 Wait Amount(等待量)设置为
1.00。 - 将 Wait Unit(等待单位)设置为
Minutes(分钟)。
- 将 Resume(恢复)设置为
- 将 Edit Fields (Set) 节点添加到 Wait 节点。
- 使用 JSON 或 Manual Mapping Mode(手动映射模式)。
- 设置一个名为
outputValue的新字段,其值为 new-date 字段的值。 - 选择 Include Other Input Fields(包括其他输入字段)选项并包括 All(所有)字段。
- 在工作流开始时添加 Schedule Trigger 节点。
- 将 Trigger Interval(触发间隔)设置为使用
Minutes(分钟)。 - 将 Minutes Between Triggers(触发之间的分钟数)设置为 30。
- 要测试你的计划,请务必激活工作流。
- 请务必将此节点连接到你开始使用的 Customer Datastore (n8n training) 节点!
- 将 Trigger Interval(触发间隔)设置为使用
工作流应如下所示:

转换日期的工作流
要检查每个节点的配置,你可以复制此工作流的 JSON 代码,然后将其粘贴到编辑器 UI 中,或将其保存为文件并从文件导入到新工作流中。有关更多信息,请参阅导出和导入工作流。
{
"name": "Course 2, Ch 2, Date exercise",
"nodes": [
{
"parameters": {},
"id": "6bf64d5c-4b00-43cf-8439-3cbf5e5f203b",
"name": "When clicking \"Execute workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
620,
280
]
},
{
"parameters": {
"operation": "getAllPeople",
"returnAll": true
},
"id": "a08a8157-99ee-4d50-8fe4-b6d7e16e858e",
"name": "Customer Datastore (n8n training)",
"type": "n8n-nodes-base.n8nTrainingCustomerDatastore",
"typeVersion": 1,
"position": [
840,
360
]
},
{
"parameters": {
"operation": "roundDate",
"date": "={{ $json.created }}",
"mode": "roundUp",
"outputFieldName": "new-date",
"options": {
"includeInputFields": true
}
},
"id": "f66a4356-2584-44b6-a4e9-1e3b5de53e71",
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"typeVersion": 2,
"position": [
1080,
360
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "7c82823a-e603-4166-8866-493f643ba354",
"leftValue": "={{ $json['new-date'] }}",
"rightValue": "1960-01-01T00:00:00",
"operator": {
"type": "dateTime",
"operation": "after"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "cea39877-6183-4ea0-9400-e80523636912",
"name": "If",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1280,
360
]
},
{
"parameters": {
"amount": 1,
"unit": "minutes"
},
"id": "5aa860b7-c73c-4df0-ad63-215850166f13",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
1480,
260
],
"webhookId": "be78732e-787d-463e-9210-2c7e8239761e"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "e058832a-2461-4c6d-b584-043ecc036427",
"name": "outputValue",
"value": "={{ $json['new-date'] }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"id": "be034e9e-3cf1-4264-9d15-b6760ce28f91",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1700,
260
]
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 30
}
]
}
},
"id": "6e8e4308-d0e0-4d0d-bc29-5131b57cf061",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
620,
480
]
}
],
"pinData": {},
"connections": {
"When clicking \"Execute workflow\"": {
"main": [
[
{
"node": "Customer Datastore (n8n training)",
"type": "main",
"index": 0
}
]
]
},
"Customer Datastore (n8n training)": {
"main": [
[
{
"node": "Date & Time",
"type": "main",
"index": 0
}
]
]
},
"Date & Time": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Customer Datastore (n8n training)",
"type": "main",
"index": 0
}
]
]
}
}
}
二进制数据#
到目前为止,你主要处理文本数据。但是,如果你想处理非文本数据,例如图像或 PDF 文件,该怎么办?这些类型的文件在二进制数字系统中表示,因此它们被视为二进制数据。在这种形式下,二进制数据不会为你提供有用的信息,因此你需要将其转换为可读形式。
在 n8n 中,你可以使用以下节点处理二进制数据:
- HTTP Request 从 Web 资源和 API 请求和发送文件。
- Read/Write Files from Disk 从运行 n8n 的机器读取和写入文件。
- Convert to File 获取输入数据并将其输出为文件。
- Extract From File 从二进制格式获取数据并将其转换为 JSON。
读取和写入文件仅在自托管 n8n 上可用
在 n8n Cloud 上无法读取和写入文件到磁盘。你将读取和写入到安装 n8n 的机器。如果你在 Docker 中运行 n8n,你的命令将在 n8n 容器中运行,而不是在 Docker 主机中运行。Read/Write Files From Disk 节点相对于 n8n 安装路径查找文件。n8n 建议使用绝对文件路径以防止任何错误。
要读取或写入二进制文件,你需要在节点的 File(s) Selector(文件选择器)参数(用于 读取操作)或节点的 File Path and Name(文件路径和名称)参数(用于写入操作)中写入文件的路径(位置)。
命名正确的路径
文件路径看起来略有不同,具体取决于你运行 n8n 的方式:
- npm:
~/my_file.json - n8n cloud / Docker:
/tmp/my_file.json
二进制练习 1#
对于我们的第一个二进制练习,让我们将 PDF 文件转换为 JSON:
- 发出 HTTP 请求以获取此 PDF 文件:
https://media.kaspersky.com/pdf/Kaspersky_Lab_Whitepaper_Anti_blocker.pdf. - 使用 Extract From File 节点将文件从二进制转换为 JSON。
显示解决方案
在 HTTP Request 节点中,你应该看到 PDF 文件,如下所示:

HTTP Request 节点获取 PDF
当你使用 Extract From File 节点将 PDF 从二进制转换为 JSON 时,结果应如下所示:

Extract From File 节点
要检查节点的配置,你可以复制下面的 JSON 工作流代码并将其粘贴到编辑器 UI 中:
{
"name": "Binary to JSON",
"nodes": [
{
"parameters": {},
"id": "78639a25-b69a-4b9c-84e0-69e045bed1a3",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
480,
520
]
},
{
"parameters": {
"url": "https://media.kaspersky.com/pdf/Kaspersky_Lab_Whitepaper_Anti_blocker.pdf",
"options": {}
},
"id": "a11310df-1287-4e9a-b993-baa6bd4265a6",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
700,
520
]
},
{
"parameters": {
"operation": "pdf",
"options": {}
},
"id": "88697b6b-fb02-4c3d-a715-750d60413e9f",
"name": "Extract From File",
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
920,
520
]
}
],
"pinData": {},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Extract From File",
"type": "main",
"index": 0
}
]
]
}
}
}
二进制练习 2#
对于我们的第二个二进制练习,让我们将一些 JSON 数据转换为二进制:
- 向 Poetry DB API
https://poetrydb.org/random/1发出 HTTP 请求。 - 使用 Convert to File 节点将返回的数据从 JSON 转换为二进制。
- 使用 Read/Write Files From Disk 节点将新的二进制文件数据写入运行 n8n 的机器。
- 要检查它是否成功,请使用 Read/Write Files From Disk 节点读取生成的二进制文件。
显示解决方案
此练习的工作流如下所示:

将 JSON 移动到二进制数据的工作流
要检查节点的配置,你可以复制下面的 JSON 工作流代码并将其粘贴到编辑器 UI 中:
{
"name": "JSON to file and Read-Write",
"nodes": [
{
"parameters": {},
"id": "78639a25-b69a-4b9c-84e0-69e045bed1a3",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
480,
520
]
},
{
"parameters": {
"url": "https://poetrydb.org/random/1",
"options": {}
},
"id": "a11310df-1287-4e9a-b993-baa6bd4265a6",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
680,
520
]
},
{
"parameters": {
"operation": "toJson",
"options": {}
},
"id": "06be18f6-f193-48e2-a8d9-35f4779d8324",
"name": "Convert to File",
"type": "n8n-nodes-base.convertToFile",
"typeVersion": 1,
"position": [
880,
520
]
},
{
"parameters": {
"operation": "write",
"fileName": "/tmp/poetrydb.json",
"options": {}
},
"id": "f2048e5d-fa8f-4708-b15a-d07de359f2e5",
"name": "Read/Write Files from Disk",
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
1080,
520
]
},
{
"parameters": {
"fileSelector": "={{ $json.fileName }}",
"options": {}
},
"id": "d630906c-09d4-49f4-ba14-416c0f4de1c8",
"name": "Read/Write Files from Disk1",
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
1280,
520
]
}
],
"pinData": {},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Convert to File",
"type": "main",
"index": 0
}
]
]
},
"Convert to File": {
"main": [
[
{
"node": "Read/Write Files from Disk",
"type": "main",
"index": 0
}
]
]
},
"Read/Write Files from Disk": {
"main": [
[
{
"node": "Read/Write Files from Disk1",
"type": "main",
"index": 0
}
]
]
}
}
}