YouTube Comment Sentiment Analyzer

工作流概述

这是一个包含16个节点的复杂工作流,主要用于自动化处理各种任务。

工作流源代码

下载
{
  "id": "xaC6zL4bWBo14xyJ",
  "meta": {
    "instanceId": "10f6e8a86649316fe7041c503c24e6d77b68a961a9f4f1f76d0100c435446092",
    "templateCredsSetupCompleted": true
  },
  "name": "YouTube Comment Sentiment Analyzer",
  "tags": [],
  "nodes": [
    {
      "id": "0bacd739-7ea3-42f5-8986-2f7d47628ee9",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        820,
        -40
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "body.items"
      },
      "typeVersion": 1
    },
    {
      "id": "236aaaab-6a9a-42d7-8645-980bf8c3254d",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1080,
        180
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "4d73v7kxEDNu3n25",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c1eda3a6-9fbe-4150-8086-c3ffebaeb2e1",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        380,
        140
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "d28f3fbf-6013-47af-ba84-3bdd9800fd3b",
      "name": "Get Video Urls from Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -200,
        -40
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 760258523,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4/edit#gid=760258523",
          "cachedResultName": "Sheet2"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4/edit?usp=drivesdk",
          "cachedResultName": "Youtube Videos Comments"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "id": "jPoTdPxgVL0vr9SQ",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "0ac06530-cfe7-4f1c-8c0a-8def2126df0f",
      "name": "check next fetch time is available or not",
      "type": "n8n-nodes-base.if",
      "position": [
        -20,
        -40
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "92084960-e023-4cd6-a5c0-ddd43275cc33",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.next_fetch_time }}",
              "rightValue": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ba42f450-3b0c-41a3-8e72-d2a38b97cfc7",
      "name": "check next fetch time is before the current time",
      "type": "n8n-nodes-base.if",
      "position": [
        160,
        80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "40c8d081-b298-46b1-850c-2322ed89d18d",
              "operator": {
                "type": "dateTime",
                "operation": "before"
              },
              "leftValue": "={{ $json.next_fetch_time }}",
              "rightValue": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "aad11f42-b976-41d7-b771-151da60391d6",
      "name": "Get Comments for video urls",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        360,
        -60
      ],
      "parameters": {
        "url": "https://www.googleapis.com/youtube/v3/commentThreads",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "responseFormat": "json"
            }
          },
          "pagination": {
            "pagination": {
              "parameters": {
                "parameters": [
                  {
                    "name": "pageToken",
                    "value": "={{ $response.body.nextPageToken }}"
                  }
                ]
              },
              "completeExpression": "={{ !$response.body.nextPageToken}}",
              "paginationCompleteWhen": "other"
            }
          }
        },
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "part",
              "value": "snippet"
            },
            {
              "name": "videoId",
              "value": "={{ $json[\"video_urls\"].match(/(?:v=|\/)([0-9A-Za-z_-]{11})/)[1] || ''}}"
            },
            {
              "name": "maxResults",
              "value": "100"
            }
          ]
        }
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "LmsYEaslJmA6CMdL",
          "name": "Query Auth account 4"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4cf1ebd0-e260-4e53-bc26-be1db2f6e7f2",
      "name": "Analyze sentiment of every comment",
      "type": "@n8n/n8n-nodes-langchain.sentimentAnalysis",
      "position": [
        1060,
        -40
      ],
      "parameters": {
        "options": {
          "categories": "Positive, Neutral, Negative",
          "systemPromptTemplate": "You are highly intelligent and accurate sentiment analyzer. Analyze the sentiment of the provided text. Categorize it into one of the following: {categories}. Use the provided formatting instructions. Only output the JSON."
        },
        "inputText": "={{ $json.snippet.topLevelComment.snippet.textOriginal }}"
      },
      "typeVersion": 1
    },
    {
      "id": "f306c5cd-6b6b-46fa-b7ef-f3ccef960931",
      "name": "Format fields as required to save in google sheet",
      "type": "n8n-nodes-base.set",
      "position": [
        1500,
        -40
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "25fb96a0-de38-4495-8473-0385a3fd5df9",
              "name": "commentId",
              "type": "string",
              "value": "={{ $json.snippet.topLevelComment.id }}"
            },
            {
              "id": "d824ecd0-89c0-4c07-992f-6a5d3421690e",
              "name": "video_url",
              "type": "string",
              "value": "=https://www.youtube.com/watch?v={{ $json.snippet.videoId }}"
            },
            {
              "id": "cdcbc3d9-ab3e-4d7d-80a7-bfe168b0ed27",
              "name": "comment",
              "type": "string",
              "value": "={{ $json.snippet.topLevelComment.snippet.textOriginal }}"
            },
            {
              "id": "20bcfe96-3904-44d2-b72a-9eb49d603c8d",
              "name": "authorName",
              "type": "string",
              "value": "={{ $json.snippet.topLevelComment.snippet.authorDisplayName }}"
            },
            {
              "id": "c92f56bf-8b37-4c4e-9ce7-b7a49d63deee",
              "name": "likes",
              "type": "string",
              "value": "={{ $json.snippet.topLevelComment.snippet.likeCount }}"
            },
            {
              "id": "7cc4fdb3-7c41-418a-bf4f-71081fe9df74",
              "name": "reply",
              "type": "string",
              "value": "={{ $json.snippet.totalReplyCount }}"
            },
            {
              "id": "9988ea66-7f31-4b2c-90ab-3cad8efabf95",
              "name": "sentiment",
              "type": "string",
              "value": "={{ $json.sentimentAnalysis.category }}"
            },
            {
              "id": "6552df27-6e04-4048-b3c2-1e1755ccac28",
              "name": "published_at",
              "type": "string",
              "value": "={{ $json.snippet.topLevelComment.snippet.publishedAt }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6cd20a6e-8bcc-44c7-a62d-e3c3c75e6d9a",
      "name": "Insert and update comment in google sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1720,
        -40
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "commentId",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "commentId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "video_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "video_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "comment",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "comment",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "authorName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "authorName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "likes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "likes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reply",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "reply",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sentiment",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "sentiment",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "published_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "published_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "commentId"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4/edit?usp=drivesdk",
          "cachedResultName": "Youtube Videos Comments"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "id": "jPoTdPxgVL0vr9SQ",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "ea240f38-1462-402b-8db2-36b3e8664c2f",
      "name": "Update last fetched time and next_fetch_time",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1940,
        -40
      ],
      "parameters": {
        "columns": {
          "value": {
            "video_urls": "={{ $('Get Video Urls from Google Sheet').item.json.video_urls }}",
            "next_fetch_time": "={{ $now.plus(5, 'min').toISO() }}",
            "last_fetched_time": "={{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "video_urls",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "video_urls",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_fetched_time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_fetched_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "next_fetch_time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "next_fetch_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "video_urls"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 760258523,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4/edit#gid=760258523",
          "cachedResultName": "Sheet2"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xoCVr_mlwn4jFcnJENtrU-_K5nkIytZ8qBXzxMq55n4/edit?usp=drivesdk",
          "cachedResultName": "Youtube Videos Comments"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "id": "jPoTdPxgVL0vr9SQ",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "610fa83c-a626-42c0-aa8b-1ebb1a6bcf44",
      "name": "No Operation, do nothing1",
      "type": "n8n-nodes-base.noOp",
      "position": [
        820,
        140
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "30570a68-78b8-434e-bb20-ea85a0689a63",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -380,
        -40
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "4fe79a97-fc39-41c0-9d2f-f07865deef5e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -440,
        -160
      ],
      "parameters": {
        "color": 5,
        "width": 2620,
        "height": 480,
        "content": "
# 🚀 YouTube Comment Sentiment Analyzer with Google Sheets & OpenAI"
      },
      "typeVersion": 1
    },
    {
      "id": "0ccb85d8-d29e-44a7-b644-49b3dcc6ce9b",
      "name": "Check Success Response",
      "type": "n8n-nodes-base.if",
      "position": [
        560,
        -60
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "bce76f94-5904-4fdb-b172-adc1134855f9",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.statusCode }}",
              "rightValue": 200
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "880f570f-6300-4659-9dcf-d47880140131",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1100,
        -500
      ],
      "parameters": {
        "width": 640,
        "height": 820,
        "content": "### **How to Use This Workflow:**
📝 **YouTube Comment Sentiment Analyzer**

1. 🔘 **Trigger:** Click \"Execute Workflow\" to run it manually.

2. 📄 Your Google Sheet should have **2 sheets**:
   - **Sheet1 (Results with Sentiment):**
     - Column A: `commentId` (YouTube comment id)
     - Column B: `video_url` (url of video)
     - Column C: `comment` (YouTube comment)
     - Column D: `authorName` (Name of author as per Youtube)
     - Column E: `likes` (Number of likes on that particular comment)
     - Column f: `reply` (Number of replies on that particular comment)
     - Column g: `sentiment` (Analyzed sentiment of the comment)
     - Column h: `published_at` (timestamp of comment published)
   
   - **Sheet2 (Video URLs):**
     - Column A: `video_urls` (list of YouTube video URLs)
     - Column B: `last_fetched_time` (timestamp of the last fetch)
     - Column C: `next_fetch_time` (time for the next fetch)

3. 🔐 **Make sure these credentials are set up**:
   - Google Sheets (Service Account)
   - YouTube Data API v3
   - OpenAI API Key (for sentiment analysis)

4. ✅ **What this workflow does**:
   - Reads **video URLs** from **Sheet2**.
   - Checks **last fetched time** (if applicable).
   - Fetches new comments from YouTube.
   - Analyzes sentiment using OpenAI.
   - Appends **comment**, **sentiment**, **video ID**, and **timestamp** to **Sheet1**.
   - Updates **last_fetched** timestamp in **Sheet2**.

5. 💡 **Tip:**
   - You can replace the **Manual Trigger** with a **Cron node** for automatic execution at specified intervals.
"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "70007187-7437-4053-b909-5057bf816906",
  "connections": {
    "Split Out": {
      "main": [
        [
          {
            "node": "Analyze sentiment of every comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Analyze sentiment of every comment",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Check Success Response": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Comments for video urls": {
      "main": [
        [
          {
            "node": "Check Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Video Urls from Google Sheet": {
      "main": [
        [
          {
            "node": "check next fetch time is available or not",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Get Video Urls from Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze sentiment of every comment": {
      "main": [
        [
          {
            "node": "Format fields as required to save in google sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format fields as required to save in google sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format fields as required to save in google sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert and update comment in google sheet": {
      "main": [
        [
          {
            "node": "Update last fetched time and next_fetch_time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "check next fetch time is available or not": {
      "main": [
        [
          {
            "node": "Get Comments for video urls",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "check next fetch time is before the current time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update last fetched time and next_fetch_time": {
      "main": [
        []
      ]
    },
    "check next fetch time is before the current time": {
      "main": [
        [
          {
            "node": "Get Comments for video urls",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format fields as required to save in google sheet": {
      "main": [
        [
          {
            "node": "Insert and update comment in google sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

功能特点

  • 自动检测新邮件
  • AI智能内容分析
  • 自定义分类规则
  • 批量处理能力
  • 详细的处理日志

技术分析

节点类型及作用

  • Splitout
  • @N8N/N8N Nodes Langchain.Lmchatopenai
  • Noop
  • Googlesheets
  • If

复杂度评估

配置难度:
★★★★☆
维护难度:
★★☆☆☆
扩展性:
★★★★☆

实施指南

前置条件

  • 有效的Gmail账户
  • n8n平台访问权限
  • Google API凭证
  • AI分类服务订阅

配置步骤

  1. 在n8n中导入工作流JSON文件
  2. 配置Gmail节点的认证信息
  3. 设置AI分类器的API密钥
  4. 自定义分类规则和标签映射
  5. 测试工作流执行
  6. 配置定时触发器(可选)

关键参数

参数名称 默认值 说明
maxEmails 50 单次处理的最大邮件数量
confidenceThreshold 0.8 分类置信度阈值
autoLabel true 是否自动添加标签

最佳实践

优化建议

  • 定期更新AI分类模型以提高准确性
  • 根据邮件量调整处理批次大小
  • 设置合理的分类置信度阈值
  • 定期清理过期的分类规则

安全注意事项

  • 妥善保管API密钥和认证信息
  • 限制工作流的访问权限
  • 定期审查处理日志
  • 启用双因素认证保护Gmail账户

性能优化

  • 使用增量处理减少重复工作
  • 缓存频繁访问的数据
  • 并行处理多个邮件分类任务
  • 监控系统资源使用情况

故障排除

常见问题

邮件未被正确分类

检查AI分类器的置信度阈值设置,适当降低阈值或更新训练数据。

Gmail认证失败

确认Google API凭证有效且具有正确的权限范围,重新进行OAuth授权。

调试技巧

  • 启用详细日志记录查看每个步骤的执行情况
  • 使用测试邮件验证分类逻辑
  • 检查网络连接和API服务状态
  • 逐步执行工作流定位问题节点

错误处理

工作流包含以下错误处理机制:

  • 网络超时自动重试(最多3次)
  • API错误记录和告警
  • 处理失败邮件的隔离机制
  • 异常情况下的回滚操作