使用 Dumpling AI 和 Google 文档的表单转博客自动化
高级
这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 17 个节点。主要使用 Code, Wait, Limit, SplitOut, Aggregate 等节点。 使用 Dumpling AI、OpenAI 和 Google 文档从关键词自动化博客创建
前置要求
- •可能需要目标 API 的认证凭证
- •OpenAI API Key
使用的节点 (17)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "hCUgw7o0NPlNWR0K",
"meta": {
"instanceId": "a1ae5c8dc6c65e674f9c3947d083abcc749ef2546dff9f4ff01de4d6a36ebfe6",
"templateCredsSetupCompleted": true
},
"name": "使用 Dumpling AI 和 Google 文档的表单转博客自动化",
"tags": [],
"nodes": [
{
"id": "5e40b2b3-8d03-46b0-b1da-a1111997da55",
"name": "表单提交(关键词)",
"type": "n8n-nodes-base.formTrigger",
"position": [
-416,
32
],
"webhookId": "1efeb31a-b7f2-4750-8c8a-5aabbdafd57d",
"parameters": {
"options": {},
"formTitle": "Blog form",
"formFields": {
"values": [
{
"fieldLabel": "Keywords"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "4e2c4c76-6d22-4a6b-abd1-8771b2ff21f7",
"name": "Dumpling AI 自动补全",
"type": "n8n-nodes-base.httpRequest",
"position": [
-192,
32
],
"parameters": {
"url": "https://app.dumplingai.com/api/v1/get-autocomplete",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $json.Keywords }}"
},
{
"name": "country",
"value": "US"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "RLFzAcGRepr5eXZB",
"name": "Dumpling AI-n8n"
}
},
"typeVersion": 4.2
},
{
"id": "99e4b141-da82-4131-a38e-d65e14307049",
"name": "分割自动补全建议",
"type": "n8n-nodes-base.splitOut",
"position": [
32,
32
],
"parameters": {
"options": {},
"fieldToSplitOut": "suggestions"
},
"typeVersion": 1
},
{
"id": "cc647e9e-fb05-4ea0-ac9c-c5c619ff0d7c",
"name": "循环建议",
"type": "n8n-nodes-base.splitInBatches",
"position": [
256,
32
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "dd3edb69-ea7c-4d45-9fec-28400e9c16d7",
"name": "请求间延迟",
"type": "n8n-nodes-base.wait",
"position": [
464,
32
],
"webhookId": "7ec6dbb9-5d73-43f1-aec9-ba1d6d6c7890",
"parameters": {},
"typeVersion": 1.1
},
{
"id": "2e768d0f-a2fa-4236-a25f-1ed2ae36a9f1",
"name": "Dumpling AI 谷歌新闻",
"type": "n8n-nodes-base.httpRequest",
"position": [
672,
32
],
"parameters": {
"url": " https://app.dumplingai.com/api/v1/search-news",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $json.value }}"
},
{
"name": "country",
"value": "US"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "RLFzAcGRepr5eXZB",
"name": "Dumpling AI-n8n"
}
},
"typeVersion": 4.2
},
{
"id": "4cc5e45e-3fd1-444b-b872-83ca62196b41",
"name": "分割新闻文章",
"type": "n8n-nodes-base.splitOut",
"position": [
864,
32
],
"parameters": {
"options": {},
"fieldToSplitOut": "news"
},
"typeVersion": 1
},
{
"id": "3f03dc09-2cbc-4c6a-a798-1a61b81a8073",
"name": "筛选文章(1-2 天前)",
"type": "n8n-nodes-base.code",
"position": [
1104,
32
],
"parameters": {
"jsCode": "// Works in n8n Code node\n// Filters only articles that are between 1 and 2 days old\n\nfunction parseRelative(relative, baseNow) {\n if (typeof relative !== 'string') return null;\n const s = relative.trim().toLowerCase();\n\n // quick rejects\n if (s.includes('yesterday')) {\n // treat \"yesterday\" as exactly 1 day ago\n return new Date(baseNow.getTime() - 24 * 3600000);\n }\n if (s.includes('week') || s.includes('month') || s.includes('year')) return null;\n\n // match \"15 hours ago\", \"2 days ago\", etc.\n const m = s.match(/(\\d+)\\s*(second|seconds|sec|secs|minute|min|minutes|mins|hour|hours|day|days)\\s*ago$/);\n if (!m) return null;\n\n const amount = parseInt(m[1], 10);\n const unit = m[2];\n\n const msMap = {\n second: 1000, seconds: 1000, sec: 1000, secs: 1000,\n minute: 60000, minutes: 60000, min: 60000, mins: 60000,\n hour: 3600000, hours: 3600000,\n day: 86400000, days: 86400000,\n };\n\n const ms = msMap[unit];\n if (!ms) return null;\n\n return new Date(baseNow.getTime() - amount * ms);\n}\n\n// Collect articles from either shape\nlet articles = [];\nif (items.length === 1 && Array.isArray(items[0].json)) {\n articles = items[0].json;\n} else {\n articles = items.map(i => i.json);\n}\n\n// Determine \"now\" (or override with present_date if provided)\nlet baseNow = new Date();\nconst present = items?.[0]?.json?.present_date;\nif (typeof present === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(present)) {\n const [y, m, d] = present.split('-').map(n => parseInt(n, 10));\n baseNow = new Date(y, m - 1, d, 12, 0, 0, 0);\n}\n\n// Define boundaries\nconst twoDaysAgo = new Date(baseNow.getTime() - 2 * 24 * 3600000);\nconst oneDayAgo = new Date(baseNow.getTime() - 1 * 24 * 3600000);\n\nconst out = [];\nfor (const a of articles) {\n const rel = a.date || a.published_time || a.publishedAt || a.pubDate || a.time || '';\n const abs = parseRelative(rel, baseNow);\n if (!abs) continue;\n\n // Keep only if between 1 and 2 days ago\n if (abs >= twoDaysAgo && abs < oneDayAgo) {\n const url = a.link || a.url || a.uri;\n if (!url) continue;\n\n out.push({ json: { URL: String(url), score: 10 } });\n }\n}\n\nreturn out;\n"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "a62c05a4-a000-4e0a-af8d-834f0623802c",
"name": "限制文章数量",
"type": "n8n-nodes-base.limit",
"position": [
1328,
32
],
"parameters": {
"maxItems": 2
},
"typeVersion": 1
},
{
"id": "30ba63a3-5ac6-4a80-ab09-39ead3320774",
"name": "Dumpling AI 爬虫",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
1568,
32
],
"parameters": {
"url": "https://app.dumplingai.com/api/v1/scrape",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "url",
"value": "={{ $json.URL }}"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "RLFzAcGRepr5eXZB",
"name": "Dumpling AI-n8n"
}
},
"typeVersion": 4.2
},
{
"id": "f1ad7937-7877-4c35-9840-27b8ac21d447",
"name": "清理和准备文章内容",
"type": "n8n-nodes-base.code",
"position": [
1776,
32
],
"parameters": {
"jsCode": "// n8n Code node, JavaScript\n\n// If the incoming item is a single item whose .json is an array,\n// make it our working array. Otherwise assume multiple items.\nconst raw = Array.isArray(items[0]?.json) ? items[0].json : items.map(i => i.json);\n\nfunction cleanMarkdown(md) {\n if (!md || typeof md !== \"string\") return \"\";\n\n let text = md;\n\n // Remove markdown images  and bare images \n text = text.replace(/!\\[[^\\]]*?\\]\\([^)]+\\)/g, \"\");\n\n // Replace markdown links [text](url) with just \"text\"\n text = text.replace(/\\[([^\\]]+)\\]\\((?:https?:\\/\\/|mailto:)[^)]+\\)/g, \"$1\");\n\n // Remove bare URLs\n text = text.replace(/https?:\\/\\/\\S+/g, \"\");\n\n // Cut everything after non article sections\n const cutMarkers = [\n /^##\\s*More videos\\b/mi,\n /^##\\s*Related Articles\\b/mi,\n /^##\\s*More Regional News\\b/mi,\n /^\\s*Share This Article\\b/mi,\n /^##\\s*About Me\\b/mi,\n ];\n for (const rx of cutMarkers) {\n const idx = text.search(rx);\n if (idx !== -1) {\n text = text.slice(0, idx);\n break;\n }\n }\n\n // Drop common clutter lines\n const dropStarts = [\n \"Skip to content\",\n \"Skip to main content\",\n \"Share\",\n \"Watch later\",\n \"Copy link\",\n \"Include playlist\",\n \"More videos\",\n \"You are signed out\",\n \"CancelConfirm\",\n \"Search\",\n \"Shopping\",\n \"Info\",\n \"Tap to unmute\",\n \"If playback does not begin\",\n \"Video Player is loading\",\n \"Play Video\",\n \"Stream Type\",\n \"Seek to live\",\n \"Remaining Time\",\n \"Playback Rate\",\n \"Chapters\",\n \"Captions\",\n \"Audio Track\",\n \"Fullscreen\",\n \"Close Modal Dialog\",\n \"Topic:\",\n ];\n text = text\n .split(\"\\n\")\n .filter(line => {\n const L = line.trim();\n if (!L) return true;\n return !dropStarts.some(s => L.startsWith(s));\n })\n .join(\"\\n\");\n\n // Remove heading markers but keep their words\n text = text.replace(/^#{1,6}\\s*/gm, \"\");\n\n // Remove blockquote markers\n text = text.replace(/^\\s*>\\s?/gm, \"\");\n\n // Remove leftover image captions such as \"(Image by ...)\"\n text = text.replace(/\\((?:Image by|Photo|GIF|Video)[^)]+\\)\\s*/gi, \"\");\n\n // Compress extra blank lines\n text = text.replace(/\\n{3,}/g, \"\\n\\n\").trim();\n\n return text;\n}\n\nconst out = raw.map(a => {\n const title = a.title || \"\";\n const content = a.content || \"\";\n return {\n json: {\n title,\n article: cleanMarkdown(content),\n },\n };\n});\n\nreturn out;\n"
},
"typeVersion": 2
},
{
"id": "e122251c-5540-4dd3-be3f-59620c1aacf2",
"name": "聚合文章",
"type": "n8n-nodes-base.aggregate",
"position": [
496,
-208
],
"parameters": {
"include": "specifiedFields",
"options": {},
"aggregate": "aggregateAllItemData",
"fieldsToInclude": "article",
"destinationFieldName": "article"
},
"typeVersion": 1
},
{
"id": "acf43fa6-f8d4-4533-8522-68640916877c",
"name": "OpenAI:生成博客草稿",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
752,
-208
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {},
"messages": {
"values": [
{
"role": "system",
"content": "=You are a professional content writer. I will provide you with raw scraped content from different articles. Your job is to create a polished, original blog post based on the ideas and insights in that content.\n\nOutput Requirements:\n- Return ONLY valid JSON (no explanations, no markdown formatting outside JSON, no comments).\n- JSON must have exactly these keys:\n {\n \"Blog_post\": \"Markdown formatted blog post\",\n \"title\": \"A clear, engaging blog post title\"\n }\n\nWriting Instructions:\n1. Write the blog post in engaging, professional, and conversational language.\n2. Use Markdown formatting: \n - Headings (#, ##, ###) for sections\n - Bold or italic where necessary\n - Lists where it improves readability\n3. Do not copy the scraped text directly. Rewrite it in your own words while keeping the meaning.\n4. Exclude clutter such as “related articles,” “share this,” or video references.\n5. Organize with a strong introduction, clear body sections, and a compelling conclusion.\n6. Add smooth transitions between sections so the blog post flows naturally.\n\n"
},
{
"content": "=---\nHere is the scraped content to base the blog post on:\n{{ JSON.stringify($json.article) }}\n---\n"
}
]
},
"jsonOutput": true
},
"credentials": {
"openAiApi": {
"id": "dd8NvMC6rvx8RITo",
"name": "OpenAi account 2"
}
},
"typeVersion": 1.8
},
{
"id": "04ee4323-3527-401c-a963-a726c7f1dad6",
"name": "Google 文档:创建博客文件",
"type": "n8n-nodes-base.googleDocs",
"position": [
1104,
-208
],
"parameters": {
"title": "={{ $json.message.content.title }}",
"folderId": "1NU00YbKNiHJptNuQZH6kgVUhLvDzE0ka"
},
"credentials": {
"googleDocsOAuth2Api": {
"id": "Ofx9WFXGfyxTK2fk",
"name": "Google Docs account"
}
},
"typeVersion": 2
},
{
"id": "bacf9175-722d-4f93-a571-4a5e4e555995",
"name": "Google 文档:插入博客内容",
"type": "n8n-nodes-base.googleDocs",
"position": [
1312,
-208
],
"parameters": {
"actionsUi": {
"actionFields": [
{
"text": "={{ $('OpenAI: Generate Blog Draft').item.json.message.content.Blog_post }}",
"action": "insert"
}
]
},
"operation": "update",
"documentURL": "={{ $json.id }}"
},
"credentials": {
"googleDocsOAuth2Api": {
"id": "Ofx9WFXGfyxTK2fk",
"name": "Google Docs account"
}
},
"typeVersion": 2
},
{
"id": "cac11f57-cf15-40ec-9c0a-49ad02b48564",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
-208
],
"parameters": {
"width": 624,
"height": 368,
"content": "## 代理分支"
},
"typeVersion": 1
},
{
"id": "d382d3f0-74fc-47d3-8b32-8e3c48f5bf40",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
704,
-384
],
"parameters": {
"width": 752,
"height": 256,
"content": "## 博客分支"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {
"Dumpling AI Autocomplete": [
{
"json": {
"credits": 1,
"suggestions": [
{
"value": "ai agents"
},
{
"value": "ai agents explained"
},
{
"value": "ai agents vs agentic ai"
},
{
"value": "ai agents course"
},
{
"value": "ai agents examples"
},
{
"value": "ai agents startup science machine"
},
{
"value": "ai agents reddit"
},
{
"value": "ai agents directory"
},
{
"value": "ai agents tools"
},
{
"value": "ai agents in action"
}
],
"searchParameters": {
"q": "AI agents",
"gl": "us",
"type": "autocomplete",
"engine": "google"
}
}
}
],
"Form Submission (Keywords)": [
{
"json": {
"Keywords": "AI agents",
"formMode": "test",
"submittedAt": "2025-08-23T10:19:28.477+10:00"
}
}
]
},
"settings": {
"executionOrder": "v1"
},
"versionId": "34bb81b5-d086-4f95-b702-3f42cb606281",
"connections": {
"a62c05a4-a000-4e0a-af8d-834f0623802c": {
"main": [
[
{
"node": "30ba63a3-5ac6-4a80-ab09-39ead3320774",
"type": "main",
"index": 0
}
]
]
},
"cc647e9e-fb05-4ea0-ac9c-c5c619ff0d7c": {
"main": [
[
{
"node": "e122251c-5540-4dd3-be3f-59620c1aacf2",
"type": "main",
"index": 0
}
],
[
{
"node": "dd3edb69-ea7c-4d45-9fec-28400e9c16d7",
"type": "main",
"index": 0
}
]
]
},
"e122251c-5540-4dd3-be3f-59620c1aacf2": {
"main": [
[
{
"node": "acf43fa6-f8d4-4533-8522-68640916877c",
"type": "main",
"index": 0
}
]
]
},
"30ba63a3-5ac6-4a80-ab09-39ead3320774": {
"main": [
[
{
"node": "f1ad7937-7877-4c35-9840-27b8ac21d447",
"type": "main",
"index": 0
}
]
]
},
"4cc5e45e-3fd1-444b-b872-83ca62196b41": {
"main": [
[
{
"node": "3f03dc09-2cbc-4c6a-a798-1a61b81a8073",
"type": "main",
"index": 0
}
]
]
},
"dd3edb69-ea7c-4d45-9fec-28400e9c16d7": {
"main": [
[
{
"node": "2e768d0f-a2fa-4236-a25f-1ed2ae36a9f1",
"type": "main",
"index": 0
}
]
]
},
"2e768d0f-a2fa-4236-a25f-1ed2ae36a9f1": {
"main": [
[
{
"node": "4cc5e45e-3fd1-444b-b872-83ca62196b41",
"type": "main",
"index": 0
}
]
]
},
"4e2c4c76-6d22-4a6b-abd1-8771b2ff21f7": {
"main": [
[
{
"node": "99e4b141-da82-4131-a38e-d65e14307049",
"type": "main",
"index": 0
}
]
]
},
"5e40b2b3-8d03-46b0-b1da-a1111997da55": {
"main": [
[
{
"node": "4e2c4c76-6d22-4a6b-abd1-8771b2ff21f7",
"type": "main",
"index": 0
}
]
]
},
"acf43fa6-f8d4-4533-8522-68640916877c": {
"main": [
[
{
"node": "04ee4323-3527-401c-a963-a726c7f1dad6",
"type": "main",
"index": 0
}
]
]
},
"04ee4323-3527-401c-a963-a726c7f1dad6": {
"main": [
[
{
"node": "bacf9175-722d-4f93-a571-4a5e4e555995",
"type": "main",
"index": 0
}
]
]
},
"99e4b141-da82-4131-a38e-d65e14307049": {
"main": [
[
{
"node": "cc647e9e-fb05-4ea0-ac9c-c5c619ff0d7c",
"type": "main",
"index": 0
}
]
]
},
"f1ad7937-7877-4c35-9840-27b8ac21d447": {
"main": [
[
{
"node": "cc647e9e-fb05-4ea0-ac9c-c5c619ff0d7c",
"type": "main",
"index": 0
}
]
]
},
"3f03dc09-2cbc-4c6a-a798-1a61b81a8073": {
"main": [
[
{
"node": "a62c05a4-a000-4e0a-af8d-834f0623802c",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 内容创作, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用Dumpling AI + GPT-4根据关键词查找TikTok视频问题
使用Dumpling AI + GPT-4根据关键词查找TikTok视频问题
Code
Wait
Limit
+
Code
Wait
Limit
16 节点Yang
内容创作
使用 Dumpling AI 从表单自动生成电影级动物视频和声音
使用GPT-4、Dumpling AI和ElevenLabs音频将表单输入转换为电影级视频
Set
Code
Wait
+
Set
Code
Wait
23 节点Yang
内容创作
使用Dumpling AI和GPT-4o生成YouTube视频创意
通过视频分析使用Dumpling AI和GPT-4o生成YouTube内容创意
Code
Wait
Gmail
+
Code
Wait
Gmail
13 节点Yang
内容创作
WordPress博客自动化专业版(深度研究)v2.1市场
使用GPT-4o、Perplexity AI和多语言支持自动化SEO优化的博客创建
If
Set
Xml
+
If
Set
Xml
125 节点Daniel Ng
内容创作
使用GPT-5和fal.ai图像从关键词到WordPress自动化SEO博客流程
使用GPT-5和fal.ai图像从关键词到WordPress自动化SEO博客流程
Set
Code
Wait
+
Set
Code
Wait
96 节点Paul
内容创作
使用Dumpling AI和HeyGen从最新AI新闻生成虚拟形象视频
使用Dumpling AI、GPT-4o和HeyGen创建AI新闻虚拟形象视频
If
Wait
Limit
+
If
Wait
Limit
15 节点Yang
内容创作