Skip to content

处理不同的数据类型#

在本章中,您将学习如何使用 n8n 核心节点 处理不同类型的数据。

HTML 和 XML 数据#

您很可能熟悉 HTML 和 XML。

HTML vs. XML

HTML 是一种用于描述网页结构和语义的标记语言。XML 看起来类似于 HTML,但标签名称不同,因为它们描述了它们所包含的数据类型。

如果您需要在 n8n 工作流中处理 HTML 或 XML 数据,请使用 HTML 节点XML 节点

使用 HTML 节点 通过引用 CSS 选择器提取网页的 HTML 内容。如果您想从网站收集结构化信息(网页抓取),这很有用。

HTML 练习#

让我们获取最新 n8n 博客文章的标题:

  1. 使用 HTTP 请求节点 向 URL https://blog.n8n.io/ 发出 GET 请求(此端点不需要身份验证)。
  2. 连接一个 HTML 节点 并配置它以提取页面上第一篇博客文章的标题。
    • 提示:如果您不熟悉 CSS 选择器或阅读 HTML,CSS 选择器 .post .item-title a 应该会有帮助!
显示解决方案
  1. 使用以下参数配置 HTTP 请求节点:
    • 身份验证:None
    • 请求方法:GET
    • URL:https://blog.n8n.io/ 结果应该如下所示:

HTTP 请求节点的结果
HTTP 请求节点的结果

  1. HTML 节点 连接到 HTTP 请求节点 并配置前者的参数:
    • 操作:Extract HTML Content
    • 源数据:JSON
    • JSON 属性:data
    • 提取值
      • :title
      • CSS 选择器.post .item-title a
      • 返回值:HTML

您可以添加更多值来提取更多数据。

结果应该如下所示:

HTML 提取节点的结果
HTML 提取节点的结果

使用 XML 节点 将 XML 转换为 JSON 和将 JSON 转换为 XML。如果您使用使用 XML 或 JSON 的不同 Web 服务,并且需要在两种格式之间获取和提交数据,则此操作很有用。

XML 练习#

第 1 章的最后练习 中,您使用了 HTTP 请求节点 向 PokéAPI 发出请求。在此练习中,我们将返回到同一个 API,但我们将输出转换为 XML:

  1. 添加一个 HTTP 请求节点,向 PokéAPI https://pokeapi.co/api/v2/pokemon 发出相同的请求。
  2. 使用 XML 节点将 JSON 输出转换为 XML。
显示解决方案
  1. 要从 PokéAPI 获取 pokemon,执行具有以下参数的 HTTP 请求节点
    • 身份验证:None
    • 请求方法:GET
    • URL:https://pokeapi.co/api/v2/pokemon
  2. 连接一个具有以下参数的 XML 节点
    • 模式:JSON to XML
    • 属性名称:data

结果应该如下所示:

XML 节点的表格视图(JSON 到 XML)
XML 节点(JSON 到 XML)– 表格视图

要以另一种方式转换数据,选择模式 XML to JSON

日期、时间和间隔数据#

日期和时间数据类型包括 DATETIMEDATETIMETIMESTAMPYEAR。日期和时间可以以不同格式传递,例如:

  • DATE:March 29 2022, 29-03-2022, 2022/03/29
  • TIME:08:30:00, 8:30, 20:30
  • DATETIME:2022/03/29 08:30:00
  • TIMESTAMP:1616108400 (Unix timestamp), 1616108400000 (Unix ms timestamp)
  • YEAR:2022, 22

有几种方法可以处理日期和时间:

有时,您可能需要暂停工作流执行。如果您知道服务不会立即处理数据或返回所有结果的速度很慢,这可能是必要的。在这些情况下,您不希望 n8n 将不完整的数据传递给下一个节点。

如果您遇到这样的情况,请在要延迟的节点后使用 等待节点等待节点 暂停工作流执行,并将在以下情况下恢复执行:

  • 在特定时间。
  • 在指定的时间间隔之后。
  • 在 webhook 调用时。

日期练习#

构建一个工作流,将您之前使用的客户数据存储节点的输入日期加上五天。然后,如果计算出的日期在 1959 年之后发生,工作流等待 1 分钟,然后设置计算出的日期作为值。工作流应该每 30 分钟触发一次。

开始:

  1. 添加选择了 Get All People 操作的 客户数据存储(n8n 培训)节点。返回全部。
  2. 添加 日期和时间节点 将数据存储中的创建日期向上舍入到月末。将此输出到字段 new-date。包含所有输入字段。
  3. 添加 If 节点 检查新的舍入日期是否在 1960-01-01 00:00:00 之后。
  4. 等待节点 添加到该节点的 True 输出,并设置它等待一分钟。
  5. 添加 编辑字段(设置)节点 设置一个名为 outputValue 的新字段为包含 new-date 的字符串。包含所有输入字段。
  6. 在工作流开始时添加 计划触发器节点 以每 30 分钟触发一次。(您可以保留手动触发器节点进行测试!)
显示解决方案
  1. 添加选择了 Get All People 操作的 客户数据存储(n8n 培训)节点
    • 选择选项 Return All
  2. 添加连接到客户数据存储节点的 日期和时间节点。选择选项 Round a Date
    • 添加 created 日期作为要舍入的 Date
    • 选择 Round Up 作为 Mode,选择 End of Month 作为 To
    • Output Field Name 设置为 new-date
    • Options 中,选择 Add Option 并使用控件 Include Input Fields
  3. 添加连接到 日期和时间节点If 节点
    • 添加 new-date 字段作为条件的第一部分。
    • 将比较设置为 Date &Time > is after
    • 添加 1960-01-01 00:00:00 作为表达式的第二部分。(这应该在 True 分支中产生 3 个项目,在 False 分支中产生 2 个项目)
  4. 等待节点 添加到 If 节点 的 True 输出。
    • Resume 设置为 After Time interval
    • Wait Amount 设置为 1.00
    • Wait Unit 设置为 Minutes
  5. 编辑字段(设置)节点 添加到 等待节点
    • 使用 JSON 或手动映射 Mode
    • 设置一个名为 outputValue 的新字段为 new-date 字段的值。
    • 选择选项 Include Other Input Fields 并包含 All 字段。
  6. 在工作流开始时添加 计划触发器节点
    • Trigger Interval 设置为使用 Minutes
    • Minutes Between Triggers 设置为 30。
    • 要测试您的计划,请确保激活工作流。
    • 确保将此节点连接到您开始的 客户数据存储(n8n 培训)节点

工作流应该如下所示:

转换日期的工作流
转换日期的工作流

要检查每个节点的配置,您可以复制此工作流的 JSON 代码,并将其粘贴到编辑器 UI 中或保存为文件并从文件导入到新工作流中。有关更多信息,请参阅导出和导入工作流

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
{
"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 中,您可以使用以下节点处理二进制数据:

读取和写入文件仅在自托管 n8n 上可用

在 n8n Cloud 上无法读取和写入磁盘文件。您将读取和写入安装 n8n 的机器。如果您在 Docker 中运行 n8n,您的命令在 n8n 容器中运行,而不是在 Docker 主机中。从磁盘读取/写入文件节点查找相对于 n8n 安装路径的文件。n8n 建议使用绝对文件路径以防止任何错误。

要读取或写入二进制文件,您需要在节点的 File(s) Selector 参数(用于读取操作)或节点的 File Path and Name 参数(用于写入操作)中写入文件的路径(位置)。

命名正确的路径

文件路径根据您运行 n8n 的方式略有不同:

  • npm: ~/my_file.json
  • n8n cloud / Docker: /tmp/my_file.json

二进制练习 1#

对于我们的第一个二进制练习,让我们将 PDF 文件转换为 JSON:

  1. 发出 HTTP 请求以获取此 PDF 文件:https://media.kaspersky.com/pdf/Kaspersky_Lab_Whitepaper_Anti_blocker.pdf.
  2. 使用 从文件提取节点 将文件从二进制转换为 JSON。
显示解决方案

HTTP 请求节点 中,您应该看到 PDF 文件,如下所示:

HTTP 请求节点获取 PDF
HTTP 请求节点获取 PDF

当您使用 从文件提取节点 将 PDF 从二进制转换为 JSON 时,结果应该如下所示:

从文件提取节点
从文件提取节点

要检查节点的配置,您可以复制下面的 JSON 工作流代码并将其粘贴到您的编辑器 UI 中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{
	"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 数据转换为二进制:

  1. 向 Poetry DB API https://poetrydb.org/random/1 发出 HTTP 请求。
  2. 使用 转换为文件节点 将返回的数据从 JSON 转换为二进制。
  3. 使用 从磁盘读取/写入文件节点 将新的二进制文件数据写入运行 n8n 的机器。
  4. 要检查它是否有效,使用 从磁盘读取/写入文件节点 读取生成的二进制文件。
显示解决方案

此练习的工作流如下所示:

将 JSON 移动到二进制数据的工作流
将 JSON 移动到二进制数据的工作流

要检查节点的配置,您可以复制下面的 JSON 工作流代码并将其粘贴到您的编辑器 UI 中:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
{
	"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
			}
			]
		]
		}
	}
}