8
n8n 中文网amn8n.com

Decodo爬虫API工作流模板(n8n自动化亚马逊图书购买报告)

高级

这是一个AI Summarization, Multimodal AI领域的自动化工作流,包含 22 个节点。主要使用 Set, Code, Slack, GoogleDrive, HttpRequest 等节点。 使用Decodo爬虫和GPT 4.1 mini提取亚马逊图书数据并生成购买报告

前置要求
  • Slack Bot Token 或 Webhook URL
  • Google Drive API 凭证
  • 可能需要目标 API 的认证凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "26kLwujfcYNYROSS",
  "meta": {
    "instanceId": "4a2e6764ba7a6bc9890d9225f4b21d570ce88fc9bd57549c89057fcee58fed0f",
    "templateCredsSetupCompleted": true
  },
  "name": "Decodo 爬虫 API 工作流模板(n8n 自动化亚马逊图书购买报告)",
  "tags": [
    {
      "id": "LAIfxZMd3ZR7hJo6",
      "name": "Decodo",
      "createdAt": "2025-09-02T04:14:42.812Z",
      "updatedAt": "2025-09-02T04:14:42.812Z"
    }
  ],
  "nodes": [
    {
      "id": "e2a6dee1-55c0-4407-841b-6bbbfddebc86",
      "name": "当点击“执行工作流”时",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        0,
        -16
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "6f8cea7d-d8f3-456f-81cd-6213b95e2d5d",
      "name": "OpenAI 聊天模型",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        928,
        208
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "PPSwAKeLQYgAPobT",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "db22753b-8bc1-468c-9705-61067a63bae2",
      "name": "结构化输出解析器",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1056,
        208
      ],
      "parameters": {
        "jsonSchemaExample": "[{\n  \"asin\": \"0399501487\",\n  \"title\": \"Lord of the Flies\",\n  \"author\": \"William Golding\",\n  \"rank\": 50,\n  \"category\": \"Literature & Fiction\",\n  \"sub_category\": \"Classics\",\n  \"rating\": 4.6,\n  \"ratings_count\": 25600,\n  \"price\": {\n    \"currency\": \"USD\",\n    \"amount\": 9.99,\n    \"format\": \"Paperback\"\n  },\n  \"url\": \"https://www.amazon.com/dp/0399501487\",\n  \"publisher\": \"Penguin\",\n  \"publication_date\": \"1959-04-15\",\n  \"language\": \"English\",\n  \"pages\": 224\n}\n]"
      },
      "typeVersion": 1.3
    },
    {
      "id": "158b0532-e82f-4044-b0a5-84b1b0ea7ffe",
      "name": "创建文档文件",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1744,
        -16
      ],
      "parameters": {
        "url": "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&supportsAllDrives=true",
        "body": "=--foo_bar_baz\nContent-Type: application/json; charset=UTF-8\n\n{\n  \"name\": \"{{ $json.Today }}\",\n  \"mimeType\": \"application/vnd.google-apps.document\",\n  \"parents\": [\"{{ $json['Drive Folder ID'] }}\"]\n}\n\n--foo_bar_baz\nContent-Type: text/markdown; charset=UTF-8\n\n{{ $('Build 📚 Book Purchase Report').item.json.markdown }}\n\n--foo_bar_baz--",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendQuery": true,
        "contentType": "raw",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "rawContentType": "multipart/related; boundary=foo_bar_baz",
        "queryParameters": {
          "parameters": [
            {
              "name": "uploadType",
              "value": "multipart"
            },
            {
              "name": "supportsAllDrives",
              "value": "true"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "boundary",
              "value": "foo_bar_baz"
            }
          ]
        },
        "nodeCredentialType": "googleDriveOAuth2Api"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "fC471es5gk5Mm900",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "fc816728-71ab-4e0e-948f-b49852644086",
      "name": "将文档转换为 PDF",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1968,
        -16
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {
          "googleFileConversion": {
            "conversion": {
              "docsToFormat": "application/pdf"
            }
          }
        },
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "fC471es5gk5Mm900",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "47b8d51c-5d4f-453c-a562-e1a3f0c94715",
      "name": "配置 Google Drive 文件夹",
      "type": "n8n-nodes-base.set",
      "position": [
        1520,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1ff0b9a4-7d60-44ec-b047-e49252f1ace9",
              "name": "Drive Folder ID",
              "type": "string",
              "value": "1IPcko8bzogO3W4mxhrW2Q017QA0Lc5MI"
            },
            {
              "id": "d64a1ac4-15db-4c84-a1db-fbd6b48084f5",
              "name": "Today",
              "type": "string",
              "value": "={{ $now.format(\"ddMMyyyyhhmmss\") }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8d06b26e-c55b-4846-b9a9-0e974b056fd9",
      "name": "产品分析器智能体",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        896,
        -16
      ],
      "parameters": {
        "text": "=Get top 10 best selling book from the below web content:\n{{ $json.text }}",
        "options": {
          "systemMessage": "You are a helpful assistant to parse the HTML content and output as well-structure JSON"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "0b6859b7-220e-432c-be18-a0931d15108d",
      "name": "爬虫 API 请求",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        448,
        -16
      ],
      "parameters": {
        "url": "https://scraper-api.decodo.com/v2/scrape",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.url }}"
            },
            {
              "name": "device_type",
              "value": "desktop"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "={{ $json.Authenticate_Token }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "6e74af84-70a1-4184-8ded-0592d40f1587",
      "name": "编辑字段",
      "type": "n8n-nodes-base.set",
      "position": [
        224,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "391aaecd-88c0-4943-9417-2d9fc6bc50b9",
              "name": "Authenticate_Token",
              "type": "string",
              "value": "Get token from your Decodo dashboard (https://dashboard.decodo.com/web-scraping-api/scraper)"
            },
            {
              "id": "859e5162-ef18-454a-9819-c1b0f2800b3f",
              "name": "url",
              "type": "string",
              "value": "https://www.amazon.com/Best-Sellers-Books/zgbs/books"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4416d72c-ac02-46ca-82d7-c896d7a30c7d",
      "name": "HTML 响应解析器",
      "type": "n8n-nodes-base.code",
      "position": [
        672,
        -16
      ],
      "parameters": {
        "jsCode": "// n8n Code node (JavaScript)\n// Input:  $input.first().json.results[0].content\n// Output: clean plain text (no HTML/JS/CSS, minimal \\n)\n\nfunction stripAll(html) {\n  if (typeof html !== 'string') return '';\n\n  // Remove scripts, styles, head, comments, svg, noscript, canvas\n  html = html.replace(/<script[\\s\\S]*?<\\/script>/gi, '');\n  html = html.replace(/<style[\\s\\S]*?<\\/style>/gi, '');\n  html = html.replace(/<head[\\s\\S]*?<\\/head>/gi, '');\n  html = html.replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, '');\n  html = html.replace(/<svg[\\s\\S]*?<\\/svg>/gi, '');\n  html = html.replace(/<canvas[\\s\\S]*?<\\/canvas>/gi, '');\n  html = html.replace(/<!--[\\s\\S]*?-->/g, '');\n\n  // Replace block-level tags with a single newline\n  const blockTags = [\n    'p','div','section','article','header','footer','nav','aside','main',\n    'h1','h2','h3','h4','h5','h6','ul','ol','li','table','tr','td','th','br','hr'\n  ];\n  for (const tag of blockTags) {\n    const rxOpen  = new RegExp(`<${tag}[^>]*>`, 'gi');\n    const rxClose = new RegExp(`</${tag}>`, 'gi');\n    html = html.replace(rxOpen, '\\n');\n    html = html.replace(rxClose, '\\n');\n  }\n\n  // Strip all remaining tags\n  let text = html.replace(/<\\/?[^>]+>/g, '');\n\n  // Decode common HTML entities\n  text = text\n    .replace(/&nbsp;/g, ' ')\n    .replace(/&amp;/g, '&')\n    .replace(/&lt;/g, '<')\n    .replace(/&gt;/g, '>')\n    .replace(/&quot;/g, '\"')\n    .replace(/&#39;/g, \"'\");\n\n  // Clean whitespace\n  text = text\n    .replace(/\\r/g, '')\n    .replace(/[ \\t]+/g, ' ')       // collapse spaces/tabs\n    .replace(/\\n[ \\t]+/g,'')    // trim spaces after newlines\n    .replace(/\\n{3,}/g, '')    // collapse 3+ newlines into 2\n    .trim();\n  \n  return text;\n}\n\n// MAIN\nconst html = $input.first().json?.results?.[0]?.content || '';\nif (!html) {\n  return [{ json: { error: 'No HTML found at json.results[0].content' } }];\n}\n\nconst text = stripAll(html);\n\nreturn [{\n  json: {\n    text,\n    chars: text.length\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "36cc67cd-75a8-442b-be19-18c6883c0509",
      "name": "上传报告到 Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2192,
        -16
      ],
      "webhookId": "4f70c69a-8b0e-4446-973c-f14e6479fcae",
      "parameters": {
        "options": {
          "fileName": "=Book Purchase Report {{ $today.format('yyyy-MM-dd') }}",
          "channelId": "C0989EJ7Z6K",
          "initialComment": "📚 Book Purchase Report"
        },
        "resource": "file",
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "4JSKt9sIRV1KGswQ",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "85e63b80-bd08-4c1f-8677-d4c87274ddd4",
      "name": "构建 📚 图书购买报告",
      "type": "n8n-nodes-base.code",
      "position": [
        1296,
        -16
      ],
      "parameters": {
        "jsCode": "// n8n Code node (JavaScript)\n// Input shape expected:\n// items[0].json.output = [ { title, author, rank, category, sub_category, rating, ratings_count, price:{currency, amount, format}, ... }, ... ]\n\nfunction median(nums) {\n  if (!nums.length) return 0;\n  const arr = [...nums].sort((a, b) => a - b);\n  const mid = Math.floor(arr.length / 2);\n  return arr.length % 2 ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2;\n}\n\nfunction sum(nums) {\n  return nums.reduce((a, b) => a + (Number.isFinite(b) ? b : 0), 0);\n}\n\nfunction mean(nums) {\n  const valid = nums.filter(n => Number.isFinite(n));\n  return valid.length ? sum(valid) / valid.length : 0;\n}\n\nfunction fmtMoney(n, currency = \"USD\") {\n  if (!Number.isFinite(n)) n = 0;\n  try {\n    return new Intl.NumberFormat(\"en-US\", { style: \"currency\", currency }).format(n);\n  } catch {\n    return `$${n.toFixed(2)}`;\n  }\n}\n\nfunction pad(str, len) {\n  return (str + '').padEnd(len, ' ');\n}\n\nfunction repeat(s, n) {\n  return Array.from({ length: n }, () => s).join('');\n}\n\nfunction safe(v, d='') { return (v === null || v === undefined) ? d : v; }\n\nfunction asBar(value, max, width = 20) {\n  if (max <= 0) return '';\n  const filled = Math.round((value / max) * width);\n  return repeat('▉', filled);\n}\n\nconst now = new Date();\nconst dateStr = now.toLocaleString('en-US', { year:'numeric', month:'short', day:'2-digit' });\n\nconst inp = $input.all();\nconst books = (inp?.[0]?.json?.output && Array.isArray(inp[0].json.output))\n  ? inp[0].json.output\n  : Array.isArray(inp?.[0]?.json) ? inp[0].json : [];\n\nconst clean = books.map(b => ({\n  title: safe(b.title, 'N/A'),\n  author: safe(b.author, 'Unknown'),\n  rank: Number.isFinite(b.rank) ? b.rank : null,\n  category: safe(b.category, 'N/A'),\n  sub_category: safe(b.sub_category, 'N/A'),\n  rating: Number.isFinite(b.rating) ? b.rating : 0,\n  ratings_count: Number.isFinite(b.ratings_count) ? b.ratings_count : 0,\n  price_amount: Number.isFinite(b?.price?.amount) ? b.price.amount : 0,\n  price_currency: safe(b?.price?.currency, 'USD'),\n  price_format: safe(b?.price?.format, 'Unknown'),\n}));\n\n// --- Core metrics ---\nconst totalBooks = clean.length;\nconst currency = clean.find(b => b.price_currency)?.price_currency || 'USD';\nconst prices = clean.map(b => b.price_amount).filter(n => Number.isFinite(n) && n >= 0);\nconst totalSpend = sum(prices);\nconst avgPrice = mean(prices);\nconst medPrice = median(prices);\nconst minPrice = prices.length ? Math.min(...prices) : 0;\nconst maxPrice = prices.length ? Math.max(...prices) : 0;\n\nconst rated = clean.filter(b => b.rating > 0);\nconst avgRating = rated.length ? mean(rated.map(b => b.rating)) : 0;\nconst ratingCoverage = rated.length;\nconst unratedCount = totalBooks - ratingCoverage;\n\n// category/subcategory counts\nconst catCount = {};\nconst subCatCount = {};\nfor (const b of clean) {\n  catCount[b.category] = (catCount[b.category] || 0) + 1;\n  subCatCount[b.sub_category] = (subCatCount[b.sub_category] || 0) + 1;\n}\n\n// formats\nconst formatCount = {};\nfor (const b of clean) {\n  formatCount[b.price_format] = (formatCount[b.price_format] || 0) + 1;\n}\n\n// top by popularity (ratings_count) and by rating (>=50 ratings)\nconst topByRatingsCount = [...clean].sort((a,b) => b.ratings_count - a.ratings_count).slice(0,5);\nconst topByRating = [...clean]\n  .filter(b => b.ratings_count >= 50 && b.rating > 0)\n  .sort((a,b) => b.rating - a.rating)\n  .slice(0,5);\n\n// price histogram (simple buckets)\nconst bucketSize = 5; // $5 buckets\nconst buckets = {};\nfor (const p of prices) {\n  const b = Math.floor(p / bucketSize) * bucketSize;\n  const label = `${fmtMoney(b, currency)}–${fmtMoney(b + bucketSize - 0.01, currency)}`;\n  buckets[label] = (buckets[label] || 0) + 1;\n}\nconst bucketEntries = Object.entries(buckets).sort((a,b) => {\n  // sort by numeric lower bound\n  const n = s => Number(s[0].replace(/[^0-9.]/g, ''));\n  return n(a) - n(b);\n});\nconst maxBucket = bucketEntries.length ? Math.max(...bucketEntries.map(([_, v]) => v)) : 0;\n\n// category table (top 5)\nconst topCats = Object.entries(catCount).sort((a,b) => b[1]-a[1]).slice(0,5);\nconst topSubCats = Object.entries(subCatCount).sort((a,b) => b[1]-a[1]).slice(0,5);\nconst topFormats = Object.entries(formatCount).sort((a,b) => b[1]-a[1]).slice(0,5);\n\n// build tables\nfunction makeKpiRow(label, value) {\n  return `| ${label} | ${value} |`;\n}\n\nfunction tableHeader(cols) {\n  return `| ${cols.join(' | ')} |\\n| ${cols.map(()=>'---').join(' | ')} |`;\n}\n\nfunction bookRow(b) {\n  const title = b.title.length > 72 ? b.title.slice(0,69) + '…' : b.title;\n  return `| ${safe(b.rank,'–')} | ${title} | ${b.author} | ${fmtMoney(b.price_amount, b.price_currency)} | ${b.rating || '–'} | ${b.ratings_count} |`;\n}\n\nconst kpiTable = [\n  tableHeader(['Metric','Value']),\n  makeKpiRow('Total Books', totalBooks),\n  makeKpiRow('Total Spend (list prices)', fmtMoney(totalSpend, currency)),\n  makeKpiRow('Avg Price', fmtMoney(avgPrice, currency)),\n  makeKpiRow('Median Price', fmtMoney(medPrice, currency)),\n  makeKpiRow('Price Range', `${fmtMoney(minPrice, currency)} – ${fmtMoney(maxPrice, currency)}`),\n  makeKpiRow('Avg Rating (rated only)', rated.length ? avgRating.toFixed(2) : '–'),\n  makeKpiRow('Rated Titles', `${ratingCoverage}/${totalBooks}`),\n].join('\\n');\n\nconst popularityTable = [\n  tableHeader(['Rank','Title','Author','Price','Rating','#Ratings']),\n  ...topByRatingsCount.map(bookRow),\n].join('\\n');\n\nconst qualityTable = [\n  tableHeader(['Rank','Title','Author','Price','Rating','#Ratings']),\n  ...topByRating.map(bookRow),\n].join('\\n');\n\nfunction kvTable(title, entries) {\n  const rows = entries.map(([k,v]) => `| ${k} | ${v} |`).join('\\n');\n  return `**${title}**\\n\\n${tableHeader(['Key','Count'])}\\n${rows}`;\n}\n\nconst catTable = kvTable('Top Categories', topCats);\nconst subCatTable = kvTable('Top Sub-Categories', topSubCats);\nconst fmtTable = kvTable('Formats', topFormats);\n\n// histogram block\nconst histLines = bucketEntries.map(([label, count]) => {\n  const bar = asBar(count, maxBucket, 24);\n  return `- ${pad(label, 22)} | ${pad(count, 3)} ${bar}`;\n}).join('\\n');\n\nconst highlights = [];\nif (topByRatingsCount[0]) {\n  highlights.push(`**Most talked-about**: _${topByRatingsCount[0].title}_ (${topByRatingsCount[0].ratings_count.toLocaleString()} ratings).`);\n}\nif (topByRating[0]) {\n  highlights.push(`**Highest rated (≥50 ratings)**: _${topByRating[0].title}_ (${topByRating[0].rating.toFixed(1)}★).`);\n}\nif (topFormats[0]) {\n  highlights.push(`**Preferred format**: ${topFormats[0][0]} (${topFormats[0][1]} titles).`);\n}\nif (topCats[0]) {\n  highlights.push(`**Top category**: ${topCats[0][0]} (${topCats[0][1]} titles).`);\n}\n\nconst recs = [];\nif (unratedCount > 0) {\n  recs.push(`Fill in missing ratings for ${unratedCount} titles to improve quality insights.`);\n}\nif (prices.some(p => p === 0)) {\n  const zeroPrices = prices.filter(p => p === 0).length;\n  recs.push(`Assign prices to ${zeroPrices} title(s) with \\$0 to avoid skewing spend/price stats.`);\n}\nif (clean.some(b => !b.rank)) {\n  recs.push(`Confirm ranks for all titles to refine top-N comparisons.`);\n}\n\nconst markdown = `\n# 📚 Book Purchase Report\n**Date:** ${dateStr}\n\n> A quick, readable snapshot of your current book list with pricing, ratings, and category insights.\n\n---\n\n## 🔎 Executive KPIs\n${kpiTable}\n\n---\n\n## ⭐ Most Popular (by #Ratings)\n${popularityTable}\n\n---\n\n## 🏆 Highest Rated (≥ 50 ratings)\n${qualityTable}\n\n---\n\n## 🧩 Breakdown\n${catTable}\n\n${subCatTable}\n\n${fmtTable}\n\n---\n\n## 💲 Price Distribution (bucket = \\$${bucketSize})\n\\`\\`\\`\n${histLines || 'No price data available.'}\n\\`\\`\\`\n\n---\n\n## ✨ Highlights\n${highlights.length ? highlights.map(x => `- ${x}`).join('\\n') : '- No highlights available yet.'}\n\n---\n\n## ✅ Suggestions\n${(recs.length ? recs : ['All good!']).map(x => `- ${x}`).join('\\n')}\n`.trim();\n\n// Also expose structured stats if you want to reuse downstream\nconst stats = {\n  totalBooks,\n  currency,\n  price: {\n    totalSpend,\n    avgPrice,\n    medianPrice: medPrice,\n    minPrice,\n    maxPrice,\n  },\n  ratings: {\n    avgRating: rated.length ? Number(avgRating.toFixed(3)) : null,\n    ratedCount: ratingCoverage,\n    unratedCount,\n  },\n  counts: {\n    byCategory: catCount,\n    bySubCategory: subCatCount,\n    byFormat: formatCount,\n  },\n};\n\nreturn [\n  {\n    json: {\n      markdown,\n      stats,\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "545fa265-c575-4b59-9919-6556e27b19c3",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1152,
        -752
      ],
      "parameters": {
        "width": 1040,
        "height": 2672,
        "content": "# Decodo 爬虫 API 工作流模板(n8n 自动化亚马逊图书购买报告)"
      },
      "typeVersion": 1
    },
    {
      "id": "1fa69470-0a75-45b4-8701-58c384d35a42",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "content": "### 1. 触发工作流执行"
      },
      "typeVersion": 1
    },
    {
      "id": "bb34c2ae-5133-4465-8955-87804b5a1ce8",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        176
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "content": "### 2. 编辑输入字段"
      },
      "typeVersion": 1
    },
    {
      "id": "5010d9c6-502b-4b71-b43a-e81b9f9445f9",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "content": "### 3. 发送爬虫 API 请求(Decodo)"
      },
      "typeVersion": 1
    },
    {
      "id": "2923973f-9b5f-4e0b-9dc1-a750a8a28ba5",
      "name": "便签说明4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        192
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "content": "### 4. 解析 HTML 响应"
      },
      "typeVersion": 1
    },
    {
      "id": "e10b101a-d2e7-4274-b47d-95862b903513",
      "name": "便签说明5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        -224
      ],
      "parameters": {
        "color": 5,
        "width": 288,
        "content": "### 5. 产品分析器智能体(LLM)"
      },
      "typeVersion": 1
    },
    {
      "id": "e7345128-92d7-40a3-862b-ed25d06309f1",
      "name": "便签 6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        160
      ],
      "parameters": {
        "color": 5,
        "width": 288,
        "content": "### 6. 构建图书购买报告"
      },
      "typeVersion": 1
    },
    {
      "id": "8959f9cc-9a4b-4a8f-a5d3-7a2144780bb2",
      "name": "便签 7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1616,
        -192
      ],
      "parameters": {
        "color": 5,
        "width": 352,
        "height": 128,
        "content": "### 创建图书购买报告 PDF"
      },
      "typeVersion": 1
    },
    {
      "id": "d8d80396-cbaf-4eae-a16e-6704c9f5fc74",
      "name": "## 为什么选择 4o 模型?👆",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2096,
        160
      ],
      "parameters": {
        "color": 5,
        "width": 288,
        "height": 144,
        "content": "### 10. 上传报告到 Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "c4d42d97-6909-49e0-9edf-7c4d65f37e0b",
      "name": "便签 9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2448,
        -48
      ],
      "parameters": {
        "width": 320,
        "height": 144,
        "content": "## 来自爬取数据的示例输出报告"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "14ac45c9-5507-4a84-8278-5e1f55d52df0",
  "connections": {
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Scraper API Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Product Analyzer Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Scraper API Request": {
      "main": [
        [
          {
            "node": "HTML Response Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create document file": {
      "main": [
        [
          {
            "node": "Convert document to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML Response Parser": {
      "main": [
        [
          {
            "node": "Product Analyzer Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Product Analyzer Agent": {
      "main": [
        [
          {
            "node": "Build 📚 Book Purchase Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert document to PDF": {
      "main": [
        [
          {
            "node": "Upload report to Slack ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Product Analyzer Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Configure Google Drive Folder ": {
      "main": [
        [
          {
            "node": "Create document file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build 📚 Book Purchase Report": {
      "main": [
        [
          {
            "node": "Configure Google Drive Folder ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - AI 摘要总结, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量22
分类2
节点类型10
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
Trung Tran

Trung Tran

@trungtran

Empowering small and medium businesses with smart automation and practical AI, no big tech team required. Youtube channel: youtube.com/@theStackExplorer

外部链接
在 n8n.io 查看

分享此工作流