自动同步公众号文章工作流

自动同步公众号文章工作流

JSON
{
  "name": "自动同步公众号文章工作流",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1540,
        180
      ],
      "id": "5a254125-e659-40e4-b4ff-785d341941e5",
      "name": "When clicking ‘Execute workflow’"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "1aead2d8-db32-4837-a7bc-4f654b159db4",
              "name": "biz",
              "value": "[\"MzIzNjc1NzUzMw==\",\"MzI3MTA0MTk1MA==\",\"MzA3MzI4MjgzMw==\"]",
              "type": "array"
            },
            {
              "id": "3152a413-b0db-4206-a571-c80df9a90b2b",
              "name": "name",
              "value": "[\"量子位\",\"新智元\",\"机器之心\"]",
              "type": "array"
            },
            {
              "id": "742495c8-fb2c-4664-8fb0-91dea7d4ce94",
              "name": "key",
              "value": "极致了ID【需改为自己的】",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -1320,
        180
      ],
      "id": "bbe2617a-d9a4-4d01-aac5-a0523aafa230",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -660,
        180
      ],
      "id": "e7eb8ed5-0da1-40c5-a26f-ce52a4aeef5f",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://www.dajiala.com/fbmain/monitor/v3/post_history",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"biz\": \"{{ $json.key }}\",\n  \"url\": \"\",\n  \"name\": \"{{ $json.value }}\",\n  \"page\": 1,\n  \"key\": \"{{ $('Edit Fields').item.json.key }}\",\n  \"verifycode\": \"\"\n}",
        "options": {
          "redirect": {
            "redirect": {}
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -440,
        100
      ],
      "id": "9f4cde6a-561e-4251-abcb-dd5f5091a430",
      "name": "HTTP Request"
    },
    {
      "parameters": {
        "url": "={{ $json.url }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "*/*"
            },
            {
              "name": "Accept-Encoding",
              "value": "deflate, gzip"
            },
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
            },
            {
              "name": "Host",
              "value": "mp.weixin.qq.com"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        0,
        0
      ],
      "id": "fdcf74f5-ce95-41d3-9fa1-9d4320160b0b",
      "name": "HTTP Request1"
    },
    {
      "parameters": {
        "operation": "extractHtmlContent",
        "extractionValues": {
          "values": [
            {
              "key": "data",
              "cssSelector": "#page-content"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        220,
        0
      ],
      "id": "a2b2458c-b9db-4f4d-a320-46260906cc92",
      "name": "HTML"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.limit",
      "typeVersion": 1,
      "position": [
        -880,
        180
      ],
      "id": "00347ab9-2584-4a24-8758-5e5eaf7af2cb",
      "name": "Limit"
    },
    {
      "parameters": {
        "fieldToSplitOut": "data",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        -220,
        100
      ],
      "id": "8b84e033-3f81-4162-a775-117a24f70142",
      "name": "Split Out1"
    },
    {
      "parameters": {
        "jsCode": "/**\n * 将Markdown文本转换为纯文本\n * @param {string} markdown - 输入的Markdown格式文本\n * @returns {string} - 转换后的纯文本字符串\n */\nfunction markdownToText(markdown) {\n    if (!markdown) return '';\n\n    let text = markdown;\n\n    // 移除代码块\n    text = text.replace(/```[\\s\\S]*?```/g, '');\n    text = text.replace(/`([^`]+)`/g, '$1');\n\n    // 移除标题符号\n    text = text.replace(/^#{1,6}\\s+/gm, '');\n\n    // 移除粗体和斜体\n    text = text.replace(/[*_]{2}([^*_]+)[*_]{2}/g, '$1'); // 粗体\n    text = text.replace(/[*_]([^*_]+)[*_]/g, '$1'); // 斜体\n\n    // 处理链接\n    text = text.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1'); // [文本](链接)\n    text = text.replace(/\\[([^\\]]+)\\]\\[[^\\]]*\\]/g, '$1'); // [文本][引用]\n\n    // 移除图片标记\n    text = text.replace(/!\\[([^\\]]*?)\\]\\([^)]+\\)/g, '$1');\n    \n    // 处理各种非标准格式的图片标记\n    text = text.replace(/!图片\\s*\\)/g, '');\n    text = text.replace(/!图片\\s*$/g, '');\n    text = text.replace(/!图片[\\s\\S]*?\\)/g, '');\n    text = text.replace(/^\\s*\\)\\s*$/gm, '');\n    text = text.replace(/^\\s*$/gm, '');\n\n    // 处理列表\n    text = text.replace(/^[\\s]*[\\-*+]\\s+/gm, ''); // 无序列表\n    text = text.replace(/^[\\s]*\\d+\\.\\s+/gm, ''); // 有序列表\n\n    // 处理引用\n    text = text.replace(/^\\s*>\\s+/gm, '');\n\n    // 处理水平分割线\n    text = text.replace(/^\\s*[-*_]{3,}\\s*$/gm, '\\n');\n\n    // 移除SVG相关标签及其内容\n    text = text.replace(/<svg[^>]*>(([\\s\\S]*?)<\\/svg>)?/gi, '');\n    \n    // 增强SVG标签清理\n    const svgElements = 'svg|rect|circle|path|line|polygon|polyline|g|defs|use|symbol|ellipse|text|image|clipPath|mask|pattern|filter|marker|linearGradient|radialGradient|stop|tspan|textPath|animate|animateMotion|animateTransform|set|foreignObject|switch|desc|title|metadata';\n    text = text.replace(new RegExp(`<(${svgElements})(\\\\s[^>]*)?\\\\/?>`,'gi'), '');\n    text = text.replace(new RegExp(`<\\\\/(${svgElements})>`,'gi'), '');\n    \n    // 移除单独的SVG标签片段\n    text = text.replace(/[\\s']+(?:rect|circle|path|g|svg|defs|use|symbol)\\s*\\/?/gi, ' ');\n    text = text.replace(/[\\s']+\\/(?:rect|circle|path|g|svg|defs|use|symbol)\\s*/gi, ' ');\n    \n    // 移除括号内的SVG标签片段\n    text = text.replace(/\\([^\\)]*?(?:rect|circle|path|g|svg)[^\\)]*?\\)/gi, '');\n    \n    // 清理SVG属性和标签片段\n    text = text.replace(/['\"\\s]+(fill|x|y|width|height|rx|ry|cx|cy|r|d|points|viewBox|xmlns)=['\"]?[^'\">\\s]*['\"]?/gi, ' ');\n    text = text.replace(/\\s+(?:\\/)?(?:rect|circle|path|g|svg|defs|use|symbol|ellipse|text)(?:\\s+|\\/)/gi, ' ');\n    text = text.replace(/\\s+\\/(?:rect|circle|path|g|svg|defs|use|symbol|ellipse|text)(?:\\s+|$)/gi, ' ');\n    \n    // 移除SVG和HTML常见属性\n    const commonAttributes = 'xmlns|version|viewBox|width|height|class|style|id|fill|stroke|d|points|transform|x|y|cx|cy|r|x1|y1|x2|y2|dx|dy|offset|gradientUnits|spreadMethod|patternUnits|patternTransform|markerWidth|markerHeight|refX|refY|orient|font-size|font-family|text-anchor|alignment-baseline|href|xlink:href|preserveAspectRatio';\n    text = text.replace(new RegExp(`\\\\s+(${commonAttributes})=[\\\"\\']([^\\\"\\']*)[\\\"\\'](?:\\\\s+|$)`,'gi'), ' ');\n    \n    // 移除data URI和编码内容\n    text = text.replace(/data:(?:[^;]+;)*(?:base64,)?[a-zA-Z0-9+/]+={0,2}/g, '');\n    text = text.replace(/%[0-9a-fA-F]{2}/g, ' ');\n    \n    // 最终清理:移除任何剩余的SVG相关内容\n    text = text.replace(/\\([^\\)]*(?:svg|rect|g|path|circle)[^\\)]*\\)/gi, '');\n    text = text.replace(/'[^']*(?:svg|rect|g|path|circle)[^']*'/gi, '');\n    text = text.replace(/\"[^\"]*(?:svg|rect|g|path|circle)[^\"]*\"/gi, '');\n    text = text.replace(/(?:\\/)?(?:svg|rect|g|path|circle|defs|use|symbol)(?:\\/)?/gi, '');\n    \n    // 移除其他HTML标签\n    text = text.replace(/<[^>]+>/g, '');\n\n    // 处理转义字符\n    text = text.replace(/\\\\([\\\\`*_{}\\[\\]()#+\\-.!])/g, '$1');\n\n    // 清理多余的空行\n    text = text.replace(/\\n\\s*\\n/g, '\\n\\n');\n    text = text.replace(/^\\s+|\\s+$/g, '');\n\n    return text;\n}\n\n/**\n * 将文本按指定长度分段\n * @param {string} text - 输入文本\n * @param {number} segmentLength - 每段文本的最大长度\n * @returns {string[]} - 分段后的文本数组\n */\nfunction splitTextIntoSegments(text, segmentLength = 1800) {\n    const segments = [];\n    let remainingText = text;\n\n    while (remainingText.length > 0) {\n        if (remainingText.length <= segmentLength) {\n            segments.push(remainingText);\n            break;\n        }\n\n        let endIndex = segmentLength;\n        // 尝试在句子或段落边界处分段\n        const nextParagraph = remainingText.indexOf('\\n\\n', endIndex - 100);\n        const nextSentence = remainingText.indexOf('. ', endIndex - 100);\n\n        if (nextParagraph !== -1 && nextParagraph < endIndex + 100) {\n            endIndex = nextParagraph;\n        } else if (nextSentence !== -1 && nextSentence < endIndex + 100) {\n            endIndex = nextSentence + 1;\n        }\n\n        segments.push(remainingText.substring(0, endIndex).trim());\n        remainingText = remainingText.substring(endIndex).trim();\n    }\n\n    return segments;\n}\n\n// 获取所有输入数据项\nconst inputItems = $input.all();\nconst results = [];\n\n// 遍历处理每个输入数据项\nfor (let i = 0; i < inputItems.length; i++) {\n    const currentItem = inputItems[i];\n    const markdownInput = currentItem.json.data;\n    \n    if (!markdownInput) {\n        // 如果没有数据,跳过这个项目\n        continue;\n    }\n    \n    const plainText = markdownToText(markdownInput);\n    const textSegments = splitTextIntoSegments(plainText);\n\n    // 将文本段落转换为规范的block对象格式\n    const blocks = textSegments.map(segment => ({\n        object: 'block',\n        type: 'paragraph',\n        paragraph: {\n            rich_text: [\n                {\n                    type: 'text',\n                    annotations: {\n                        bold: false,\n                        strikethrough: false,\n                        underline: false,\n                        italic: false,\n                        code: false,\n                        color: 'default'\n                    },\n                    text: {\n                        content: segment\n                    }\n                }\n            ]\n        }\n    }));\n\n    // 只返回blocks字段\n    results.push({\n        json: {\n            blocks: blocks\n        }\n    });\n}\n\nreturn results;\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ],
      "id": "aa48ed34-8002-42c1-84e4-8412ccbc994a",
      "name": "将Markdown文本转换为纯文本"
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://api.notion.com/v1/blocks/{{ $json.id }}/children",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "notionApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "children",
              "value": "={{ $json.blocks }}"
            }
          ]
        },
        "options": {
          "batching": {
            "batch": {
              "batchSize": 1,
              "batchInterval": 5000
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        180
      ],
      "id": "d90ab579-1acf-4e0f-a6f5-b3bf30df1787",
      "name": "HTTP Request2",
      "credentials": {
        "notionApi": {
          "id": "p9ESbt4TrdVy1Eq0",
          "name": "Notion account"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        660,
        100
      ],
      "id": "f8cda93f-baa4-4f00-8323-f18ed5768cbc",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "const array1 = $input.first().json.biz;\nconst array2 = $input.first().json.name;\nconst combined = [];\n\nfor (let i = 0; i < array1.length; i++) {\n  combined.push({\n    key: array1[i],\n    value: array2[i]\n  });\n}\n\nreturn combined.map(item => ({ json: item }));\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1100,
        180
      ],
      "id": "44c229a5-fb2a-49db-a037-d35cc816f145",
      "name": "Code"
    },
    {
      "parameters": {
        "content": "## 文章同步完成后动作\n- 发送Telegram通知\n- 执行内容加工工作流,如:日报工作流、小红书发布工作流等",
        "height": 360,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        20
      ],
      "typeVersion": 1,
      "id": "c8a3ef38-5ccf-41db-b97f-2e6c9bc2251d",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "value": "22c977e7-bf54-80fe-8606-e6291091d347",
          "mode": "list",
          "cachedResultName": "AI资讯",
          "cachedResultUrl": "https://www.notion.so/22c977e7bf5480fe8606e6291091d347"
        },
        "title": "={{ $json.title }}",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "标题|title",
              "title": "={{ $json.title }}"
            },
            {
              "key": "url|rich_text",
              "textContent": "={{ $json.url }}"
            },
            {
              "key": "时间|rich_text",
              "textContent": "={{ $json.post_time_str }}"
            },
            {
              "key": "来源|rich_text",
              "textContent": "={{ $('Loop Over Items').item.json.value }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2.2,
      "position": [
        380,
        200
      ],
      "id": "76a42023-6d48-49e9-8e2d-bcb83fac8469",
      "name": "Create a database page",
      "credentials": {
        "notionApi": {
          "id": "p9ESbt4TrdVy1Eq0",
          "name": "Notion account"
        }
      }
    }
  ],
  "pinData": {},
  "connections": {
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Split Out1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML": {
      "main": [
        [
          {
            "node": "将Markdown文本转换为纯文本",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out1": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create a database page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "将Markdown文本转换为纯文本": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "HTTP Request2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request2": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a database page": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cd2c82a4-1f94-406d-88c1-844e20e7f548",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "ee5a0f120935b4b9d760798993ffeb282a815d20023e81bf0157ea4e4d3aad64"
  },
  "id": "kn2URDK94wsWOj4F",
  "tags": []
}
JSON
{
    "biz": "{{ $json.key }}",
    "url": "",
    "name": "{{ $json.value }}",
    "page": 1,
    "key": "{{ $('Edit Fields').item.json.key }}",
    "verifycode":""
}