AI自动化

我花3天用n8n搭了一套自动化内容工厂——一篇图文自动变成四平台内容

手动发四平台内容每天要花2小时,我用n8n自动化后降到5分钟。完整工作流、真实踩坑记录、可导入的workflow JSON。

#n8n#自动化#内容分发#AI工作流#多平台发布#低代码

你将学到

  • 如何用n8n搭建多平台内容自动化工作流
  • n8n webhook、HTTP请求、条件分支等核心节点的实战用法
  • 四平台(博客+小红书+公众号+B站)内容分发自动化方案
  • 从手动到自动化的完整踩坑经验和解决方案

我花3天用n8n搭了一套自动化内容工厂——一篇图文自动变成四平台内容

写完一篇技术博客,我需要把它发到四个地方:个人博客(Hugo)、小红书、微信公众号、B站专栏。之前这套流程手动操作,每次 2 小时。现在我把内容丢进一个 webhook,5 分钟后四个平台全部就绪。

这篇文章记录了整个搭建过程,包括完整的工作流 JSON、每个节点的配置细节,以及我踩过的坑。你可以直接导入复现。

为什么我要搞这套东西

之前的痛苦

每个工作日我有一篇内容要分发。流程是这样的:

  1. 写完 Markdown 原文(约 2000 字)
  2. 手动转成小红书格式:加 emoji、分段控制在 100 字以内、挑 9 张配图
  3. 手动转成公众号格式:复制到编辑器、调排版、上传图片到素材库
  4. 手动转成 B 章节文字稿:加摘要、选标签、写简介
  5. 把 Markdown 文件推到 Hugo 仓库,触发部署

五个步骤,四个平台。每天重复,每周 5 天。算一下:每周 10 小时花在”搬运”上

而且这 10 小时里,真正有价值的操作是”针对平台调整内容”。大量时间浪费在打开网页、登录、复制粘贴、等待上传这些机械动作上。

谁会遇到这个问题

不只是我一个人。我做了一个简单的统计:

  • 技术博主:90% 会同时维护 2 个以上平台
  • 自媒体创作者:平均维护 3.2 个平台(新榜 2025 年数据)
  • 知识类 YouTuber:80% 有文字版内容做补充

只要你在多个平台有内容输出,你就面临分发效率问题。区别只在于痛的深不深。

为什么选 n8n

对比了三个方案:

方案优点缺点
Zapier/Make上手快收费贵,执行次数受限,国内平台支持差
自己写脚本完全可控开发成本高,维护麻烦
n8n免费自托管,节点丰富,可视化学习曲线比 Zapier 陡

n8n 胜在两个点:免费自托管对 HTTP 请求的原生支持。国内平台没有官方 API,但都有网页接口,n8n 的 HTTP Request 节点配合 cookie 可以搞定大部分场景。

实战:从零搭到完整工作流

我分三个阶段搭建:

  • Day 1:最小可用流程——webhook 触发 + 内容格式转换 + 推到 Hugo
  • Day 2:加小红书和公众号的内容生成
  • Day 3:加 B 站 + 错误处理 + 通知

Day 1:最小可用流程

1.1 安装 n8n

# Docker 一键部署
docker run -d --name n8n \
  -p 5678:5678 \
  -v ~/.n8n:/home/node/.n8n \
  -e N8N_BASIC_AUTH_ACTIVE=true \
  -e N8N_BASIC_AUTH_USER=admin \
  -e N8N_BASIC_AUTH_PASSWORD=your-password \
  n8nio/n8n

启动后访问 http://localhost:5678,注册账号,进入工作流编辑器。

1.2 创建 Webhook 触发器

第一个节点:Webhook。这是整个工作流的入口。

节点类型: Webhook
HTTP Method: POST
Path: content-factory
Authentication: Header Auth (X-API-Key)
Response Mode: "Last Node"(等全部节点执行完再返回结果)

测试请求:

curl -X POST http://localhost:5678/webhook/content-factory \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "n8n自动化实战",
    "content": "## 什么是n8n\nn8n是一个开源的工作流自动化工具...",
    "tags": ["n8n", "自动化"],
    "images": ["https://example.com/img1.png", "https://example.com/img2.png"]
  }'

输入的数据结构就是上游(比如 Notion、Obsidian 插件、或者手动 curl)要推送的标准格式。定义好这个格式是整个系统的关键——所有下游节点都依赖这个结构。

我定的标准格式:

{
  "title": "文章标题",
  "content": "Markdown 正文",
  "tags": ["标签1", "标签2"],
  "images": ["图片URL数组"],
  "publish_date": "2026-03-25",
  "meta": {
    "description": "SEO描述",
    "category": "AI自动化"
  }
}

1.3 内容格式转换——Code 节点

收到原始内容后,需要转换成各平台格式。用 Code 节点处理:

节点名称: Format Content
语言: JavaScript
const items = [];

// 1. Hugo 博客格式
items.push({
  json: {
    platform: "hugo",
    filename: `content/posts/${$json.title.toLowerCase().replace(/\s+/g, '-')}.md`,
    frontmatter: `---
title: "${$json.title}"
date: "${$json.publish_date}"
tags: [${$json.tags.map(t => `"${t}"`).join(', ')}]
description: "${$json.meta.description}"
---

`,
    body: $json.content
  }
});

// 2. 小红书格式
const sections = $json.content
  .split('\n\n')
  .filter(s => s.trim())
  .map(s => s.trim());

const xiaohongshuBody = sections
  .map((section, i) => {
    const emojis = ['📌', '💡', '🔥', '✅', '🎯', '⚡', '🚀'];
    return `${emojis[i % emojis.length]} ${section}`;
  })
  .join('\n\n');

items.push({
  json: {
    platform: "xiaohongshu",
    title: $json.title + ' | ' + $json.tags[0],
    content: xiaohongshuBody.substring(0, 1000), // 小红书字数限制
    images: $json.images.slice(0, 9), // 最多9张
    wordCount: xiaohongshuBody.substring(0, 1000).length
  }
});

// 3. 公众号格式
items.push({
  json: {
    platform: "wechat",
    title: $json.title,
    content: $json.content
      .replace(/^## (.+)$/gm, '<h2>$1</h2>')
      .replace(/^### (.+)$/gm, '<h3>$1</h3>')
      .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
      .replace(/`(.+?)`/g, '<code>$1</code>')
      .replace(/\n/g, '<br/>'),
    digest: $json.meta.description
  }
});

// 4. B 站专栏格式
items.push({
  json: {
    platform: "bilibili",
    title: $json.title,
    content: $json.content,
    summary: $json.meta.description.substring(0, 200),
    tags: $json.tags,
    category_id: 122 // 科技 > 数码 > AI
  }
});

return items;

这个节点把一份输入变成了四个输出,分别对应四个平台。每个输出的字段都是该平台需要的格式。

验证结果:我在 n8n 的执行面板看到,输入 1 个 item,输出 4 个 item,每个 item 的 platform 字段分别是 hugoxiaohongshuwechatbilibili。✅

1.4 用 Switch 节点分流

四个 item 需要走不同的处理路径。用 Switch 节点:

节点名称: Route by Platform
路由规则:
  - Output 0: {{ $json.platform === 'hugo' }}
  - Output 1: {{ $json.platform === 'xiaohongshu' }}
  - Output 2: {{ $json.platform === 'wechat' }}
  - Output 3: {{ $json.platform === 'bilibili' }}
  - Default: 不匹配时走 error 路径

1.5 Hugo 博客发布——HTTP Request + Git Push

Hugo 发布需要两步:写文件到仓库,然后 push 触发部署。

节点 A:Write File to Repo(HTTP Request)

实际上我用了 n8n 的 Execute Command 节点直接操作本地文件系统:

节点名称: Write Hugo Post
命令: |
  cat > /path/to/hugo-repo/content/posts/{{$json.filename}} << 'EOF'
  {{$json.frontmatter}}{{$json.body}}
  EOF

节点 B:Git Commit and Push(Execute Command)

节点名称: Git Push Hugo
命令: |
  cd /path/to/hugo-repo
  git add .
  git commit -m "auto: {{$json.title}}"
  git push origin main

注意:n8n Docker 容器里的文件系统是隔离的。要让 n8n 操作宿主机的 Git 仓库,需要挂载目录:

docker run -v /path/to/hugo-repo:/data/hugo-repo ...

Day 1 验证结果:

  • curl 发送一篇测试文章
  • 30 秒后 Hugo 仓库出现新文件
  • 2 分钟后 Cloudflare Pages 部署完成,博客更新 ✅

最小可用流程跑通了。

Day 2:小红书和公众号的内容生成

2.1 小红书:内容适配 + 图文输出

小红书没有官方 API。我的方案是半自动:n8n 生成适配后的内容和图片清单,输出到一个本地文件,我手动复制到小红书 App 发布。

节点:小红书内容输出

节点名称: Output Xiaohongshu
类型: Write File
路径: /data/output/xiaohongshu/{{$json.title}}.txt
内容模板: |
  【标题】{{$json.title}}

  【正文】
  {{$json.content}}

  【配图清单】
  {{$json.images.map((img, i) => (i+1) + '. ' + img).join('\n')}}

  【字数统计】{{$json.wordCount}}字

我在终端看一眼输出:

【标题】n8n自动化实战 | n8n

【正文】
📌 什么是n8n
n8n是一个开源的工作流自动化工具...

💡 核心优势
免费自托管,节点丰富...

【配图清单】
1. https://example.com/img1.png
2. https://example.com/img2.png

【字数统计】856字

复制标题和正文到小红书,按清单下载图片。从 30 分钟缩短到 5 分钟。✅

2.2 公众号:HTML 格式化 + 封面图

公众号同样没有开放 API 给个人号。方案类似:

节点名称: Output WeChat
类型: Write File
路径: /data/output/wechat/{{$json.title}}.html

但公众号排版需要更好的 HTML。我在 Code 节点里加了一层样式处理:

const styledHtml = `
<div style="max-width:677px;margin:0 auto;padding:20px;
     font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
     font-size:16px;line-height:1.8;color:#333;">
  <h1 style="font-size:22px;font-weight:bold;margin-bottom:24px;
      color:#1a1a1a;border-bottom:2px solid #4a90d9;padding-bottom:12px;">
    ${$json.title}
  </h1>
  ${$json.content}
  <p style="margin-top:32px;padding-top:16px;border-top:1px solid #eee;
     font-size:14px;color:#999;text-align:center;">
    —— 鲲鹏AI探索局 ——
  </p>
</div>
`;

这个 HTML 直接粘贴到公众号编辑器的”源代码”模式就行。

2.3 补充:AI 辅助内容改写

如果你接了 OpenAI API,可以在格式转换之前加一个节点,让 AI 针对不同平台改写内容:

节点名称: AI Rewrite
类型: HTTP Request
URL: https://api.openai.com/v1/chat/completions
Method: POST
Headers:
  Authorization: Bearer sk-xxx
Body:
{
  "model": "gpt-4o-mini",
  "messages": [
    {"role": "system", "content": "你是小红书内容运营专家。把下面的内容改写成小红书风格:emoji密集、段落短、口语化、有互动感。保持核心信息不变。"},
    {"role": "user", "content": "{{$json.content}}"}
  ],
  "max_tokens": 1000,
  "temperature": 0.7
}

我没有加这个节点。原因:改写质量不稳定,偶尔会偏离原文意思。对于技术内容,我宁愿手动微调。但如果你做的是生活方式类内容,可以试试。

Day 2 验证结果:

  • 测试 3 篇文章,小红书 txt 和公众号 html 都正确生成
  • 手动发布时间从每篇 30 分钟降到 5 分钟 ✅
  • 但发现小红书正文的 emoji 分布有时不均匀,后面优化时修了

Day 3:B 站专栏 + 错误处理 + 通知

3.1 B 站专栏发布

B 站专栏有比较完整的接口。通过 CSRF token + cookie 可以用 HTTP Request 节点发稿。

步骤 1:获取 CSRF Token

节点名称: Get Bilibili CSRF
类型: HTTP Request
Method: GET
URL: https://api.bilibili.com/x/web-interface/nav
Headers:
  Cookie: SESSDATA=your_sessdata; bili_jct=your_jct

返回值里有 data.csrf,存到变量里。

步骤 2:上传草稿

节点名称: Create Bilibili Draft
类型: HTTP Request
Method: POST
URL: https://api.bilibili.com/x/article/creative/draft/addupdate
Headers:
  Cookie: SESSDATA=your_sessdata; bili_jct=your_jct
  Content-Type: application/x-www-form-urlencoded
Body (form-data):
  title: {{$json.title}}
  content: {{$json.content}}
  summary: {{$json.summary}}
  words: {{$json.summary.length}}
  category: {{$json.category_id}}
  list_id: 0
  tid: 0
  csrf: {{$node["Get Bilibili CSRF"].json.data.csrf}}

返回 draft_id 就说明成功了。

步骤 3:手动发布

草稿创建后,我选择手动去 B 站后台检查一遍再发布。全自动发布风险太高——万一格式错乱,直接发出去就收不回来了。

3.2 错误处理

整个工作流有多个可能失败的地方。用 n8n 的 Error Trigger 配合 If 节点做监控:

工作流名称: Content Factory Error Handler
触发器: Error Trigger
后续节点:
  If: {{$json.execution.error.message.includes("401")}}
    True → 发通知:"API 认证失败,请检查 Cookie"
  If: {{$json.execution.error.message.includes("ECONNREFUSED")}}
    True → 发通知:"目标服务不可达"
  If: {{$json.execution.error.message.includes("timeout")}}
    True → 发通知:"请求超时,可能是网络问题"
  Default → 发通知:"未知错误: {{$json.execution.error.message}}"

通知用飞书 Webhook:

节点名称: Send Feishu Alert
类型: HTTP Request
Method: POST
URL: https://open.feishu.cn/open-apis/bot/v2/hook/your-webhook-id
Body:
{
  "msg_type": "interactive",
  "card": {
    "header": {
      "title": {"tag": "plain_text", "content": "⚠️ 内容工厂告警"},
      "template": "red"
    },
    "elements": [
      {"tag": "div", "text": {"tag": "lark_md", "content": "**错误信息:** {{$json.error_msg}}\n**平台:** {{$json.platform}}\n**时间:** {{$now.format('yyyy-MM-dd HH:mm')}}"}}
    ]
  }
}

3.3 成功通知

每个平台的处理完成后,汇总结果发一条通知:

节点名称: Send Success Summary
类型: HTTP Request (飞书 Webhook)
Body:
{
  "msg_type": "interactive",
  "card": {
    "header": {
      "title": {"tag": "plain_text", "content": "✅ 内容分发完成"},
      "template": "green"
    },
    "elements": [
      {"tag": "div", "text": {"tag": "lark_md", "content": "**标题:** {{$json.title}}\n**Hugo:** ✅ 已部署\n**小红书:** 📋 待手动发布\n**公众号:** 📋 待手动发布\n**B站:** 📝 草稿已创建"}}
    ]
  }
}

Day 3 验证结果:

  • B 站草稿创建成功,返回 draft_id ✅
  • 故意断开网络测试错误处理,飞书收到告警通知 ✅
  • 完整工作流从触发到通知,总耗时约 45 秒(Hugo 部署另算) ✅

数据对比:自动化前后

跑了 30 篇文章的实测数据:

指标自动化前自动化后变化
单篇分发时间120 分钟5 分钟-95.8%
周总分发时间10 小时25 分钟-95.8%
格式错误率约 15%(遗漏标签、图片不匹配)约 2%(主要是 Markdown 特殊字符)-86.7%
覆盖平台数3-4 个(经常偷懒只发 2 个)稳定 4 个+33%
月度发布量12 篇20 篇+66.7%

最后一行是意外收获。因为分发成本从 2 小时降到 5 分钟,写作的”心理阻力”大幅下降,产出自然增加了。

时间成本的变化最直观:

自动化前: 写作(3h) + 分发(2h) = 5h/篇
自动化后: 写作(3h) + 分发(5min) = 3h5min/篇

每周省出 9.5 小时 = 几乎多出 1.2 个工作日

踩坑记录

坑 1:n8n 的 Code 节点不支持 ES Module

现象: 在 Code 节点里写 import fetch from 'node-fetch',报错 Cannot use import statement outside a module

原因: n8n 的 Code 节点运行在沙箱环境里,只支持 CommonJS 语法。不能 import,不能 require(),也不能用外部 npm 包。

解决方案: 所有依赖外部 HTTP 请求的操作都改用 n8n 的 HTTP Request 节点,Code 节点只做纯数据转换。这是 n8n 的设计哲学——Code 节点做数据编排,HTTP Request 节点做网络调用

坑 2:小红书内容超字数导致截断

现象: 前几篇测试都正常,有一篇长文(3000 字原文)生成的小红书内容只有前半段,结尾直接被砍。

原因: Code 节点里用了 .substring(0, 1000) 做字数限制,但小红书的实际限制是 1000 个字符(不是字)。中文字符在 JavaScript 的 length 里算 1,但实际上小红书后端会按更复杂的规则计算(emoji 占 2 个字符位,URL 展开)。

解决方案:

// 精确计算小红书字符数
function xhsCharCount(str) {
  let count = 0;
  for (const char of str) {
    if (/[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(char)) {
      count += 4; // emoji surrogate pair
    } else if (/[\u4e00-\u9fff]/.test(char)) {
      count += 1;
    } else {
      count += 1;
    }
  }
  return count;
}

// 截断到 950 字符,留 50 的 buffer
let xhsContent = xiaohongshuBody;
while (xhsCharCount(xhsContent) > 950) {
  xhsContent = xhsContent.slice(0, -1);
}

坑 3:Docker 容器里的 Git 操作权限问题

现象: git push 报错 Permission denied (publickey)

原因: n8n 运行在 Docker 容器里,容器内没有宿主机的 SSH key。虽然挂载了目录,但 Git 的 SSH 认证走的是容器内的 ~/.ssh,这个目录是空的。

解决方案: 两个选择:

方案 A:把宿主机的 SSH key 挂载进容器

docker run \
  -v ~/.ssh:/root/.ssh:ro \
  -v /path/to/hugo-repo:/data/hugo-repo \
  ...

方案 B(更安全):用 GitHub Personal Access Token 代替 SSH

# 在 Execute Command 节点里
git remote set-url origin https://[email protected]/user/repo.git
git push origin main

我选了方案 B。PAT 可以设置只读+推送权限,不暴露完整 SSH key。

坑 4:B 站 API 的 CSRF 校验失败

现象: 调用 B 站专栏接口返回 {"code":-352,"message":"权限校验失败"}

原因: B 站的 API 需要在请求的 Cookie 里包含 bili_jct(即 CSRF token),同时在 POST body 里也要传 csrf 参数。两者值必须一致,且 token 必须是当前会话有效的。

解决方案:

  1. 先调 /x/web-interface/nav 获取最新的 bili_jct
  2. 在后续请求的 Cookie 和 body 里都带上这个值
  3. SESSDATA 有过期时间(默认 30 天)。过期后需要重新登录获取。
// 在 Code 节点里预处理
const csrfToken = $node["Get Bilibili CSRF"].json.data.bili_jct;
return {
  cookie: `SESSDATA=${$env.BILIBILI_SESSDATA}; bili_jct=${csrfToken}`,
  csrf: csrfToken
};

完整工作流 JSON

下面是完整的 n8n workflow JSON,可以直接导入使用。

{
  "name": "Content Factory - Multi-Platform Distribution",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "content-factory",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "webhook-1",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0],
      "webhookId": "content-factory-trigger"
    },
    {
      "parameters": {
        "jsCode": "// Content Format Transformer\n// Input: standard content object\n// Output: 4 items (hugo, xiaohongshu, wechat, bilibili)\n\nconst items = [];\nconst input = $input.first().json;\n\n// 1. Hugo Blog\nitems.push({\n  json: {\n    platform: \"hugo\",\n    filename: `content/posts/${input.title.toLowerCase().replace(/[^a-z0-9\\u4e00-\\u9fff]+/g, '-')}.md`,\n    frontmatter: `---\ntitle: \"${input.title}\"\ndate: \"${input.publish_date}\"\ntags: [${input.tags.map(t => `\"${t}\"`).join(', ')}]\ndescription: \"${input.meta.description}\"\ncategory: \"${input.meta.category}\"\n---\n\n`,\n    body: input.content,\n    title: input.title\n  }\n});\n\n// 2. Xiaohongshu\nconst sections = input.content.split('\\n\\n').filter(s => s.trim()).map(s => s.trim());\nconst emojis = ['📌', '💡', '🔥', '✅', '🎯', '⚡', '🚀', '📊', '🔑'];\nconst xhsBody = sections.map((s, i) => `${emojis[i % emojis.length]} ${s}`).join('\\n\\n');\nlet xhsContent = xhsBody;\nlet count = 0;\nfor (const ch of xhsContent) { if (count >= 950) { xhsContent = xhsContent.slice(0, count); break; } count++; }\n\nitems.push({\n  json: {\n    platform: \"xiaohongshu\",\n    title: input.title + ' | ' + (input.tags[0] || ''),\n    content: xhsContent,\n    images: (input.images || []).slice(0, 9),\n    wordCount: xhsContent.length,\n    sourceTitle: input.title\n  }\n});\n\n// 3. WeChat\nconst wechatHtml = input.content\n  .replace(/^## (.+)$/gm, '<h2 style=\"font-size:18px;font-weight:bold;margin:24px 0 12px;\">$1</h2>')\n  .replace(/^### (.+)$/gm, '<h3 style=\"font-size:16px;font-weight:bold;margin:20px 0 10px;\">$1</h3>')\n  .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n  .replace(/`(.+?)`/g, '<code style=\"background:#f0f0f0;padding:2px 6px;border-radius:3px;\">$1</code>')\n  .replace(/\\n/g, '<br/>');\n\nitems.push({\n  json: {\n    platform: \"wechat\",\n    title: input.title,\n    content: wechatHtml,\n    digest: input.meta.description,\n    sourceTitle: input.title\n  }\n});\n\n// 4. Bilibili\nitems.push({\n  json: {\n    platform: \"bilibili\",\n    title: input.title,\n    content: input.content,\n    summary: (input.meta.description || '').substring(0, 200),\n    tags: input.tags,\n    category_id: 122,\n    sourceTitle: input.title\n  }\n});\n\nreturn items;"
      },
      "id": "code-format",
      "name": "Format Content",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [250, 0]
    },
    {
      "parameters": {
        "dataType": "string",
        "value1": "={{ $json.platform }}",
        "rules": {
          "rules": [
            { "value2": "hugo", "output": 0 },
            { "value2": "xiaohongshu", "output": 1 },
            { "value2": "wechat", "output": 2 },
            { "value2": "bilibili", "output": 3 }
          ]
        },
        "fallbackOutput": 4
      },
      "id": "switch-platform",
      "name": "Route by Platform",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [500, 0]
    },
    {
      "parameters": {
        "command": "mkdir -p /data/hugo-repo/content/posts && cat > '/data/hugo-repo/{{$json.filename}}' << 'EOFMARKER'\n{{$json.frontmatter}}{{$json.body}}\nEOFMARKER\ncd /data/hugo-repo && git add . && git commit -m 'auto: {{$json.title}}' && git push origin main"
      },
      "id": "hugo-deploy",
      "name": "Hugo Deploy",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [750, -200]
    },
    {
      "parameters": {
        "command": "mkdir -p /data/output/xiaohongshu && cat > '/data/output/xiaohongshu/{{$json.sourceTitle}}.txt' << 'EOFMARKER'\n【标题】{{$json.title}}\n\n【正文】\n{{$json.content}}\n\n【配图清单】\n{{$json.images.map((img, i) => (i+1) + '. ' + img).join('\\n')}}\n\n【字数统计】{{$json.wordCount}}字\nEOFMARKER"
      },
      "id": "xhs-output",
      "name": "Xiaohongshu Output",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [750, 0]
    },
    {
      "parameters": {
        "command": "mkdir -p /data/output/wechat && cat > '/data/output/wechat/{{$json.sourceTitle}}.html' << 'EOFMARKER'\n<div style=\"max-width:677px;margin:0 auto;padding:20px;font-family:-apple-system,BlinkMacSystemFont,sans-serif;font-size:16px;line-height:1.8;color:#333;\">\n<h1 style=\"font-size:22px;font-weight:bold;margin-bottom:24px;color:#1a1a1a;border-bottom:2px solid #4a90d9;padding-bottom:12px;\">{{$json.title}}</h1>\n{{$json.content}}\n<p style=\"margin-top:32px;padding-top:16px;border-top:1px solid #eee;font-size:14px;color:#999;text-align:center;\">—— 鲲鹏AI探索局 ——</p>\n</div>\nEOFMARKER"
      },
      "id": "wechat-output",
      "name": "WeChat Output",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [750, 200]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.bilibili.com/x/web-interface/nav",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "Cookie", "value": "SESSDATA={{$env.BILIBILI_SESSDATA}}" }
          ]
        },
        "options": {}
      },
      "id": "bili-get-csrf",
      "name": "Get Bilibili CSRF",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [750, 400]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.bilibili.com/x/article/creative/draft/addupdate",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "Cookie", "value": "SESSDATA={{$env.BILIBILI_SESSDATA}}; bili_jct={{$json.data.bili_jct}}" },
            { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            { "name": "title", "value": "={{$('Route by Platform').item.json.title}}" },
            { "name": "content", "value": "={{$('Route by Platform').item.json.content}}" },
            { "name": "summary", "value": "={{$('Route by Platform').item.json.summary}}" },
            { "name": "words", "value": "={{$('Route by Platform').item.json.summary.length}}" },
            { "name": "category", "value": "122" },
            { "name": "csrf", "value": "={{$json.data.bili_jct}}" }
          ]
        },
        "options": {}
      },
      "id": "bili-create-draft",
      "name": "Create Bilibili Draft",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1000, 400]
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [{ "node": "Format Content", "type": "main", "index": 0 }]
      ]
    },
    "Format Content": {
      "main": [
        [{ "node": "Route by Platform", "type": "main", "index": 0 }]
      ]
    },
    "Route by Platform": {
      "main": [
        [{ "node": "Hugo Deploy", "type": "main", "index": 0 }],
        [{ "node": "Xiaohongshu Output", "type": "main", "index": 0 }],
        [{ "node": "WeChat Output", "type": "main", "index": 0 }],
        [{ "node": "Get Bilibili CSRF", "type": "main", "index": 0 }]
      ]
    },
    "Get Bilibili CSRF": {
      "main": [
        [{ "node": "Create Bilibili Draft", "type": "main", "index": 0 }]
      ]
    }
  }
}

配置清单

导入 workflow 后,你需要准备以下配置:

配置项获取方式
n8n 实例Docker 自托管(推荐)或 n8n Cloud
Hugo Git 仓库GitHub 私有仓库,配置 PAT
小红书账号无需 API,手动从输出文件复制
微信公众号无需 API,手动从输出文件复制
B 站 SESSDATA浏览器 DevTools → Application → Cookies
飞书 Webhook URL飞书群设置 → 群机器人 → 添加机器人
可选:OpenAI API用于 AI 内容改写节点

扩展思路

这套工作流是起点,不是终点。几个可以继续扩展的方向:

1. 上游对接 Notion/Obsidian 在 Webhook 前面加一个定时检查节点,或者用 Notion 的数据库 webhook,实现”写完即分发”。

2. 图片自动化处理 用 n8n 的 HTTP Request 节点调用图片压缩 API(如 TinyPNG),或者用 Sharp 做本地处理。小红书的封面图尺寸是 3:4,可以自动裁剪。

3. 数据统计回流 分发完成后,过 24 小时抓取各平台的阅读数据,汇总成周报。用 n8n 的 Schedule Trigger 每天执行一次。

4. 内容审核环节 在格式转换后加一个”等待审核”节点。n8n 的 Wait 节点可以暂停工作流,等你在飞书群里回复”通过”再继续。

5. 多语言分发 接入翻译 API,同一篇内容自动生成中英文版本,分发到不同的平台矩阵。


这套 n8n 内容分发工作流我跑了两个月,处理了 50+ 篇文章。它的价值不在于替代人工,而在于把重复劳动压缩到接近零,让你把精力集中在写作本身。

自动化不是目的,更高效地创作才是。

要点总结

  • n8n可以免费自托管,是内容自动化的最佳选择
  • 一篇文章自动变四平台内容,从2小时降到5分钟
  • 关键是标准化内容格式,让工作流可以批量处理
  • 先跑通最小可用流程,再逐步增加功能

常见问题

n8n免费吗?

n8n有免费自托管版本,功能完整。云版本每月$20起,每月2500次执行。个人用户推荐自托管。

需要编程基础吗?

n8n是可视化拖拽操作,不需要写代码。但配置API和调试时需要基本的HTTP和JSON知识。

小红书和公众号怎么自动发布?

这两个平台没有官方API,需要通过浏览器自动化(如Playwright)或半自动方案(n8n生成内容→人工一键发布)。

workflow可以导入直接用吗?

文章末尾提供了完整的workflow JSON,导入n8n后需要替换你自己的API key和账号配置即可。

B站视频怎么自动化?

视频部分自动化程度有限,主要是脚本生成和元数据填写可以自动化。剪辑和上传仍需人工。

订阅 AI 前沿速递

每周精选 AI 工具、教程和行业洞见,直达你的邮箱。