CAPSOLVER
博客
如何使用 CapSolver 在 n8n 中求解 GeeTest V3:完整集成指南

如何使用 CapSolver 在 n8n 中求解 GeeTest V3:完整集成指南

Logo of CapSolver

Rajinder Singh

Deep Learning Researcher

18-Mar-2026

GeeTest V3 是网络上部署最广泛的行为验证码之一。与简单的复选框挑战不同,GeeTest V3 使用交互式谜题——滑动验证、图标选择和单词匹配——来区分人类和机器人。它常见于登录页面、注册表单以及亚洲乃至全球范围内的数据密集型网站。

如果您可以在 n8n 工作流中自动解决 GeeTest V3——无论是构建可重用的解决器 API、抓取受验证码保护的网站,还是自动化登录表单——所有这些都无需编写一行传统代码,那会怎么样?

在本指南中,您将学习如何将 n8n(一个可视化工作流自动化工具)与 CapSolver(一个由 AI 驱动的验证码解决服务)结合起来,按需解决 GeeTest V3 挑战——无论是作为独立的 API 端点还是作为更大自动化工作流中的一个步骤。

您将构建什么:

解决器 API——一个可重用的端点,您的其他工具可以调用:

  • 一个 GeeTest V3 解决器 API

直接使用工作流——CapSolver 作为更大自动化中的一个步骤嵌入:

  • 一个价格和产品抓取器,用于解决 GeeTest V3,获取受保护页面,并在价格变化时发出警报
  • 一个账户登录自动化,在提交凭据之前解决 GeeTest V3

什么是 GeeTest V3?

GeeTest V3 是一个挑战-响应式验证码系统,通过交互式任务验证用户。与 reCAPTCHA(使用单个令牌)或 Cloudflare Turnstile(隐形运行)不同,GeeTest V3 呈现需要用户交互的可见谜题:

  • 滑动拼图——拖动滑块完成拼图块
  • 图标点击——按正确顺序点击特定图标
  • 单词匹配——选择与提示匹配的字符

从解决的角度来看,GeeTest V3 有两个关键参数:

  • gt——一个按站点标识符(类似于站点密钥)。这是静态的——它在会话之间不会改变。
  • challenge——一个按会话令牌。这是动态的——它每次都会改变,并在大约 60-120 秒内过期。

这个动态的 challenge 参数是与其他验证码类型的主要区别。每个解决 GeeTest V3 的工作流都需要一个额外步骤,在将其发送到 CapSolver 之前获取一个新的挑战。

解决方案格式:与 reCAPTCHA 或 Turnstile 返回单个令牌不同,GeeTest V3 返回三个独立的值

  • challenge——已解决的挑战字符串
  • validate——验证哈希
  • seccode——安全码

这些作为三个表单字段提交:geetest_challengegeetest_validategeetest_seccode

GeeTest V3 与 V4: GeeTest V4 使用不同的 API 结构(captcha_id 而不是 gt,没有单独的 challenge 获取)。本指南专门介绍 V3。如果您在页面源代码中看到 captcha_id,则表示您正在处理 V4。


先决条件

在开始之前,请确保您具备以下条件:

  1. 一个 n8n 实例——自托管n8n Cloud
  2. 一个 CapSolver 账户——在此注册并获取您的 API 密钥
  3. CapSolver n8n 节点——已作为官方节点在 n8n 中可用(无需安装)

重要提示: 确保您的 CapSolver 账户中有足够的余额。GeeTest V3 解决任务会根据使用情况消耗积分。


在 n8n 中设置 CapSolver

CapSolver 作为 n8n 中的官方集成提供——无需安装社区节点。您可以在构建工作流时直接在节点面板中找到它。

由于它是官方集成,您需要在 n8n 中创建凭据,以便 CapSolver 节点可以使用您的账户进行身份验证。

步骤 1:打开凭据页面

转到您的 n8n 实例并导航到 Settings -> Credentials。您将在此处看到所有已配置的凭据。

n8n 凭据页面显示 CapSolver 账户

步骤 2:创建 CapSolver 凭据

  1. 点击 Create credential(右上角)
  2. 搜索 "CapSolver" 并选择 CapSolver API
  3. 输入您的 API Key——直接从 CapSolver Dashboard 复制
  4. Allowed HTTP Request Domains 保持为 All(默认)
  5. 点击 Save

n8n 将自动测试连接。您应该会看到一个绿色的**“Connection tested successfully”**横幅,确认您的 API 密钥有效。

CapSolver 凭据配置与成功连接测试

重要提示: 您的工作流中的每个 CapSolver 节点都将引用此凭据。您只需创建一次——所有解决器工作流都将共享相同的凭据。

现在您已准备好构建您的 GeeTest V3 解决器工作流!


如何识别 GeeTest V3 参数

在解决 GeeTest V3 挑战之前,您需要找到三件事:gt 参数、挑战 API 端点,并了解 challenge 值是如何动态获取的。

方法 1:开发者工具网络选项卡

  1. 打开开发者工具F12)-> 网络选项卡
  2. 在页面上触发 GeeTest 挑战
  3. 查找 URL 中包含 gt= 或响应中包含 "gt""challenge" 字段的请求
  4. 常见端点模式:
    • /api/geetest/register
    • /gt/register-slide
    • /captcha?gt=...
  5. 响应通常如下所示:
json 复制代码
{
  "gt": "81dc9bdb52d04dc20036dbd8313ed055",
  "challenge": "4a8a08f09d37b73795649038408b5f33ab",
  "success": 1,
  "new_captcha": true
}

理解动态挑战

这是 GeeTest V3 自动化最重要的概念:

  • gt 值在每个站点是静态的——它在会话之间保持不变
  • challenge 值是动态的——它每次都会改变,并在约 60-120 秒内过期
  • 您必须在向 CapSolver 发送解决请求之前立即获取一个新的 challenge
  • 挑战 API 端点是特定于站点的(例如,https://example.com/api/geetest/register

这意味着每个 GeeTest V3 工作流在 CapSolver 节点之前都需要一个额外的 HTTP 请求节点来获取新的挑战。这是与 reCAPTCHA 或 Turnstile 工作流的关键结构差异。

提示: 在挑战 API URL 中添加 ?t={{ Date.now() }} 作为缓存清除参数,以确保您始终获得新的挑战。

有关识别验证码参数的详细指南,请查看 CapSolver 官方文档


工作流:GeeTest V3 解决器 API

此工作流创建一个 POST 端点,接受 GeeTest V3 参数并返回已解决的挑战。与 reCAPTCHA 或 Turnstile 解决器不同,调用者必须提供 challenge 值(新获取的)以及 gtwebsiteURL

n8n 中的 GeeTest V3 解决器工作流

工作原理

工作流由四个节点组成:

  1. Webhook——接收带有 GeeTest V3 参数的传入 POST 请求
  2. GeeTest V3——将挑战发送到 CapSolver 并等待解决方案
  3. CapSolver 错误?——IF 节点,根据解决是否失败($json.error 不为空)进行分支
  4. 响应 Webhook——成功时返回解决方案,失败时返回 {"error": "..."}

节点配置

1. Webhook 节点

设置
HTTP 方法 POST
路径 solver-geetest-v3
响应 Response Node

这将在以下位置创建端点:https://your-n8n-instance.com/webhook/solver-geetest-v3

2. CapSolver GeeTest V3 节点

参数 描述
操作 GeeTest V3 必须设置为 GeeTest V3
类型 GeeTestTaskProxyLess 唯一可用选项——无代理变体
网站 URL ={{ $json.body.websiteURL }} 带有 GeeTest 挑战的页面的 URL
GT ={{ $json.body.gt }} 每个站点的 GeeTest 标识符
挑战 ={{ $json.body.challenge }} 动态的每个会话挑战(必须是新的)
GeeTest API 服务器子域 (可选) 如果站点使用自定义 GeeTest API 服务器

还要在节点中选择您的 CapSolver 凭据

3. CapSolver 错误?节点 (IF)

设置
条件 ={{ $json.error }} 不为空
真分支 路由到错误响应 Webhook 节点
假分支 路由到成功响应 Webhook 节点

这使得画布上的错误路径明确。CapSolver 节点在错误时继续(onError: continueRegularOutput),因此失败会以 { "error": "..." } 的形式到达此处,而不是使工作流崩溃。

4. 响应 Webhook 节点

成功分支(CapSolver 错误?的假输出):

设置
响应方式 JSON
响应正文 ={{ JSON.stringify($json.data) }}

测试

向您的 webhook 端点发送 POST 请求:

bash 复制代码
curl -X POST https://your-n8n-instance.com/webhook/solver-geetest-v3 \
  -H "Content-Type: application/json" \
  -d '{
    "websiteURL": "https://example.com/login",
    "gt": "81dc9bdb52d04dc20036dbd8313ed055",
    "challenge": "4a8a08f09d37b73795649038408b5f33ab"
  }'

预期响应:

json 复制代码
{
  "taskId": "abc123...",
  "solution": {
    "challenge": "4a8a08f09d37b73795649038408b5f33",
    "validate": "68f0c05d0c8a8b2b1e2f3a4b5c6d7e8f",
    "seccode": "68f0c05d0c8a8b2b1e2f3a4b5c6d7e8f|jordan"
  },
  "status": "ready"
}

重要提示: 请求正文中的 challenge 必须是新获取的。如果您发送过期的挑战,CapSolver 将无法解决它。挑战通常在 60-120 秒内过期。

导入此工作流

复制以下 JSON 并通过 Menu -> Import from JSON 导入到 n8n 中:

点击展开工作流 JSON
json 复制代码
{
  "name": "GeeTest V3 Scraping — Price & Product Details — CapSolver + Schedule + Webhook",
  "nodes": [
    {
      "parameters": {
        "content": "## GeeTest V3 抓取 — 价格和产品监控\n\n**适用对象:** 在受 GeeTest V3 保护的网站上监控价格或产品数据的团队。\n\n**功能:** 解决 GeeTest V3,获取产品页面,通过 CSS 选择器提取价格和名称,与存储值进行比较,并在发生变化时发出警报。\n\n**工作原理:**\n1. 计划(每 6 小时)或 Webhook 触发流程\n2. CapSolver 解决 GeeTest V3 挑战\n3. HTTP 请求使用已解决的令牌获取产品页面\n4. HTML 节点提取价格和产品名称\n5. 代码节点比较当前价格与存储价格 → 在发生变化时发出警报\n\n**设置:**\n1. 在 **Settings → Credentials** 下添加您的 CapSolver API 密钥\n2. 替换占位符 URL 和站点密钥\n3. 更新提取数据中的 CSS 选择器以匹配您的目标页面\n4. 将构建警报输出连接到您的通知渠道",
        "height": 560,
        "width": 460,
        "color": 1
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1220,
        -380
      ],
      "id": "sticky-blog-main-1773678228108-1",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "### 计划路径\n每 6 小时自动运行。\n结果存储在工作流静态数据中,用于跨执行比较。",
        "height": 480,
        "width": 2200,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -740,
        -280
      ],
      "id": "sticky-blog-section-1773678228108-2",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "### Webhook 路径\n按需触发 — 相同逻辑,将结果作为 JSON 响应返回。",
        "height": 480,
        "width": 2200,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -740,
        140
      ],
      "id": "sticky-blog-section-1773678228108-3",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -700,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888801",
      "name": "Every 6 Hours"
    },
    {
      "parameters": {
        "url": "https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -400,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888802",
      "name": "Fetch GeeTest Challenge"
    },
    {
      "parameters": {
        "operation": "GeeTest V3",
        "websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
        "gt": "={{ $json.gt }}",
        "challenge": "={{ $json.challenge }}",
        "optional": {}
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -96,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888803",
      "name": "Solve GeeTest V3",
      "credentials": {
        "capSolverApi": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "CapSolver account"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://YOUR-TARGET-SITE.com/product-page",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "user-agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
            },
            {
              "name": "content-type",
              "value": "application/x-www-form-urlencoded"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "geetest_challenge",
              "value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.challenge }}"
            },
            {
              "name": "geetest_validate",
              "value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.validate }}"
            },
            {
              "name": "geetest_seccode",
              "value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.seccode }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        208,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888804",
      "name": "Fetch Product Page"
    },
    {
      "parameters": {
        "operation": "extractHtmlContent",
        "extractionValues": {
          "values": [
            {
              "key": "price",
              "cssSelector": ".product-price, [data-price], .price",
              "returnValue": "text",
              "returnArray": false
            },
            {
              "key": "productName",
              "cssSelector": "h1, .product-title",
              "returnValue": "text",
              "returnArray": false
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        512,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888805",
      "name": "Extract Data"
    },
    {
      "parameters": {
        "jsCode": "// Get current and previous price from workflow static data\nconst staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || \'Product\';\n\n// Parse numeric values for comparison\nconst parsePrice = (str) => {\n  if (!str) return null;\n  const match = str.match(/[\\d,]+\\.?\\d*/);\n  return match ? parseFloat(match[0].replace(\\'\\', \'\')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\n// Update stored price\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? \'dropped\' : \'increased\') : \'unchanged\';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : \'0\';\n\nreturn [{\n  json: {\n    productName,\n    currentPrice,\n    previousPrice: previousPrice || \'first check\',\n    changed,\n    direction,\n    diff: changed ? `\\$${diff}` : null,\n    checkedAt: new Date().toISOString()\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888806",
      "name": "Compare Data"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "price-if-001",
              "leftValue": "={{ $json.changed }}",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1104,
        0
      ],
      "id": "88888888-8888-8888-8888-888888888807",
      "name": "Data Changed?"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "alert-001",
              "name": "alert",
              "value": "=Price {{ $json.direction }} for {{ $json.productName }}: {{ $json.previousPrice }} → {{ $json.currentPrice }} ({{ $json.direction === \'dropped\' ? \'-\' : \'+\' }}{{ $json.diff }})",
              "type": "string"
            },
            {
              "id": "alert-002",
              "name": "severity",
              "value": "={{ $json.direction === \'dropped\' ? \'deal\' : \'info\' }}",
              "type": "string"
            },
            {
              "id": "alert-003",
              "name": "checkedAt",
              "value": "={{ $json.checkedAt }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1408,
        -80
      ],
      "id": "88888888-8888-8888-8888-888888888808",
      "name": "Build Alert"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "nc-001",
              "name": "status",
              "value": "no_change",
              "type": "string"
            },
            {
              "id": "nc-002",
              "name": "currentPrice",
              "value": "={{ $json.currentPrice }}",
              "type": "string"
            },
            {
              "id": "nc-003",
              "name": "checkedAt",
              "value": "={{ $json.checkedAt }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1408,
        128
      ],
      "id": "88888888-8888-8888-8888-888888888809",
      "name": "No Change"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "price-monitor-geetest-v3",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -700,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888810",
      "name": "Webhook Trigger",
      "webhookId": "88888888-aaaa-bbbb-cccc-888888888810",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "url": "https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -400,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888811",
      "name": "Fetch GeeTest Challenge [Webhook]"
    },
    {
      "parameters": {
        "operation": "GeeTest V3",
        "websiteURL": "https://YOUR-TARGET-SITE.com/product-page",
        "gt": "={{ $json.gt }}",
        "challenge": "={{ $json.challenge }}",
        "optional": {}
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -96,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888812",
      "name": "Solve GeeTest V3 [Webhook]",
      "credentials": {
        "capSolverApi": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "CapSolver account"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://YOUR-TARGET-SITE.com/product-page",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "user-agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
            },
            {
              "name": "content-type",
              "value": "application/x-www-form-urlencoded"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "geetest_challenge",
              "value": "={{ $(\'Solve GeeTest V3 [Webhook]\').item.json.data.solution.challenge }}"
            },
            {
              "name": "geetest_validate",
              "value": "={{ $(\'Solve GeeTest V3 [Webhook]\').item.json.data.solution.validate }}"
            },
            {
              "name": "geetest_seccode",
              "value": "={{ $(\'Solve GeeTest V3 [Webhook]\').item.json.data.solution.seccode }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        208,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888813",
      "name": "Fetch Product Page [Webhook]"
    },
    {
      "parameters": {
        "operation": "extractHtmlContent",
        "sourceData": "json",
        "dataPropertyName": "data",
        "extractionValues": {
          "values": [
            {
              "key": "price",
              "cssSelector": ".product-price, [data-price], .price",
              "returnValue": "text",
              "returnArray": false
            },
            {
              "key": "productName",
              "cssSelector": "h1, .product-title",
              "returnValue": "text",
              "returnArray": false
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        512,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888814",
      "name": "Extract Data [Webhook]"
    },
    {
      "parameters": {
        "jsCode": "// Get current and previous price from workflow static data\nconst staticData = $workflow.staticData;\nconst currentPrice = $input.first().json.price;\nconst previousPrice = staticData.lastPrice;\nconst productName = $input.first().json.productName || \'Product\';\n\n// Parse numeric values for comparison\nconst parsePrice = (str) => {\n  if (!str) return null;\n  const match = str.match(/[\\d,]+\\.?\\d*/);\n  return match ? parseFloat(match[0].replace(\\'\\', \'\')) : null;\n};\n\nconst currentNum = parsePrice(currentPrice);\nconst previousNum = parsePrice(previousPrice);\n\n// Update stored price\nstaticData.lastPrice = currentPrice;\nstaticData.lastChecked = new Date().toISOString();\n\nconst changed = previousNum !== null && currentNum !== null && currentNum !== previousNum;\nconst direction = changed ? (currentNum < previousNum ? \'dropped\' : \'increased\') : \'unchanged\';\nconst diff = changed ? Math.abs(currentNum - previousNum).toFixed(2) : \'0\';\n\nreturn [{\n  json: {\n    productName,\n    currentPrice,\n    previousPrice: previousPrice || \'first check\',\n    changed,\n    direction,\n    diff: changed ? `\\$${diff}` : null,\n    checkedAt: new Date().toISOString()\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888815",
      "name": "Compare Data [Webhook]"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "price-if-002",
              "leftValue": "={{ $json.changed }}",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1104,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888816",
      "name": "Data Changed? [Webhook]"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "alert-004",
              "name": "alert",
              "value": "=Price {{ $json.direction }} for {{ $json.productName }}: {{ $json.previousPrice }} → {{ $json.currentPrice }} ({{ $json.direction === \'dropped\' ? \'-\' : \'+\' }}{{ $json.diff }})",
              "type": "string"
            },
            {
              "id": "alert-005",
              "name": "severity",
              "value": "={{ $json.direction === \'dropped\' ? \'deal\' : \'info\' }}",
              "type": "string"
            },
            {
              "id": "alert-006",
              "name": "checkedAt",
              "value": "={{ $json.checkedAt }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1408,
        340
      ],
      "id": "88888888-8888-8888-8888-888888888817",
      "name": "Build Alert [Webhook]"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "nc-004",
              "name": "status",
              "value": "no_change",
              "type": "string"
            },
            {
              "id": "nc-005",
              "name": "currentPrice",
              "value": "={{ $json.currentPrice }}",
              "type": "string"
            },
            {
              "id": "nc-006",
              "name": "checkedAt",
              "value": "={{ $json.checkedAt }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1408,
        548
      ],
      "id": "88888888-8888-8888-8888-888888888818",
      "name": "No Change [Webhook]"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json) }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        1712,
        420
      ],
      "id": "88888888-8888-8888-8888-888888888819",
      "name": "Respond to Webhook [Webhook]"
    }
  ],
  "connections": {
    "Every 6 Hours": {
      "main": [
        [
          {
            "node": "Fetch GeeTest Challenge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GeeTest Challenge": {
      "main": [
        [
          {
            "node": "Solve GeeTest V3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V3": {
      "main": [
        [
          {
            "node": "Fetch Product Page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Product Page": {
      "main": [
        [
          {
            "node": "Extract Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Data": {
      "main": [
        [
          {
            "node": "Compare Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Data": {
      "main": [
        [
          {
            "node": "Data Changed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Changed?": {
      "main": [
        [
          {
            "node": "Build Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Fetch GeeTest Challenge [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GeeTest Challenge [Webhook]": {
      "main": [
        [
          {
            "node": "Solve GeeTest V3 [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V3 [Webhook]": {
      "main": [
        [
          {
            "node": "Fetch Product Page [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Product Page [Webhook]": {
      "main": [
        [
          {
            "node": "Extract Data [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Data [Webhook]": {
      "main": [
        [
          {
            "node": "Compare Data [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Data [Webhook]": {
      "main": [
        [
          {
            "node": "Data Changed? [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Changed? [Webhook]": {
      "main": [
        [
          {
            "node": "Build Alert [Webhook]",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Change [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Alert [Webhook]": {
      "main": [
        [
          {
            "node": "Respond to Webhook [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Change [Webhook]": {
      "main": [
        [
          {
            "node": "Respond to Webhook [Webhook]",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}

工作流:账户登录自动化 — 解决 GeeTest V3 并提交凭据

此工作流自动化了 GeeTest V3 保护的登录表单的端到端提交。它在提交凭据之前解决 GeeTest V3 挑战。

工作原理

此工作流由五个节点组成:

  1. Webhook——接收触发登录自动化的传入 POST 请求
  2. 获取 GeeTest 挑战——向目标站点发出 HTTP 请求以获取新的 challenge
  3. 解决 GeeTest V3——将 gtchallengewebsiteURL 发送到 CapSolver
  4. 提交登录表单——向目标站点发出 HTTP POST 请求,包含凭据和已解决的 GeeTest V3 令牌
  5. 响应 Webhook——返回登录结果

节点配置

1. Webhook 节点

设置
HTTP 方法 POST
路径 login-geetest-v3
响应 Response Node

这将在以下位置创建端点:https://your-n8n-instance.com/webhook/login-geetest-v3

2. 获取 GeeTest 挑战 (HTTP Request)

设置
URL https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}
选项 Full Response = false

这将返回包含 gtchallenge 值的 JSON 响应。

3. 解决 GeeTest V3 (CapSolver)

参数
操作 GeeTest V3
网站 URL https://YOUR-TARGET-SITE.com/login
GT ={{ $json.gt }}
挑战 ={{ $json.challenge }}

还要选择您的 CapSolver 凭据

4. 提交登录表单 (HTTP Request)

设置
方法 POST
URL https://YOUR-TARGET-SITE.com/login
内容类型 form-urlencoded
正文参数 username=YOUR_USERNAMEpassword=YOUR_PASSWORDgeetest_challenge={{ $(\'Solve GeeTest V3\').item.json.data.solution.challenge }}geetest_validate={{ $(\'Solve GeeTest V3\').item.json.data.solution.validate }}geetest_seccode={{ $(\'Solve GeeTest V3\').item.json.data.solution.seccode }}

重要提示: 确保将 YOUR_USERNAMEYOUR_PASSWORD 替换为实际凭据。此外,您可能需要调整表单字段名称以匹配目标站点的 HTML。

5. 响应 Webhook (Success/Failure)

设置
响应方式 JSON
响应正文 ={{ JSON.stringify($json) }}

测试

向您的 webhook 端点发送 POST 请求:

bash 复制代码
curl -X POST https://your-n8n-instance.com/webhook/login-geetest-v3 \
  -H "Content-Type: application/json" \
  -d 

预期响应(成功):

json 复制代码
{
  "status": "success",
  "message": "Login successful",
  "solution": {
    "challenge": "...",
    "validate": "...",
    "seccode": "..."
  }
}

预期响应(失败):

json 复制代码
{
  "status": "failed",
  "message": "Login failed: Invalid credentials or captcha",
  "error": "..."
}

导入此工作流

复制以下 JSON 并通过 Menu -> Import from JSON 导入到 n8n 中:

点击展开工作流 JSON
json 复制代码
{
  "name": "Account Login Automation — Solve GeeTest V3 & Submit Credentials",
  "nodes": [
    {
      "parameters": {
        "content": "## 账户登录自动化 — 解决 GeeTest V3 并提交凭据\n\n**适用对象:** 需要自动化登录受 GeeTest V3 保护的账户的团队。\n\n**功能:** 获取 GeeTest V3 挑战,使用 CapSolver 解决,然后使用已解决的令牌和用户凭据提交登录表单。\n\n**工作原理:**\n1. Webhook 触发流程\n2. HTTP 请求获取新的 GeeTest V3 挑战\n3. CapSolver 解决挑战\n4. HTTP 请求提交登录表单,包含已解决的 GeeTest V3 令牌和用户凭据\n5. Webhook 响应登录结果\n\n**设置:**\n1. 在 **Settings → Credentials** 下添加您的 CapSolver API 密钥\n2. 替换占位符 URL 和凭据\n3. 调整表单字段名称以匹配您的目标站点\n4. 激活工作流",
        "height": 480,
        "width": 460,
        "color": 1
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1020,
        -280
      ],
      "id": "sticky-login-main-1773678228108-1",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "login-geetest-v3",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -700,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999901",
      "name": "Webhook Trigger",
      "webhookId": "99999999-aaaa-bbbb-cccc-999999999901",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "url": "https://YOUR-TARGET-SITE.com/api/geetest/register?t={{ Date.now() }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -400,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999902",
      "name": "Fetch GeeTest Challenge"
    },
    {
      "parameters": {
        "operation": "GeeTest V3",
        "websiteURL": "https://YOUR-TARGET-SITE.com/login",
        "gt": "={{ $json.gt }}",
        "challenge": "={{ $json.challenge }}",
        "optional": {}
      },
      "type": "n8n-nodes-capsolver.capSolver",
      "typeVersion": 1,
      "position": [
        -96,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999903",
      "name": "Solve GeeTest V3",
      "credentials": {
        "capSolverApi": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "CapSolver account"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://YOUR-TARGET-SITE.com/login",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "user-agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
            },
            {
              "name": "content-type",
              "value": "application/x-www-form-urlencoded"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "username",
              "value": "YOUR_USERNAME"
            },
            {
              "name": "password",
              "value": "YOUR_PASSWORD"
            },
            {
              "name": "geetest_challenge",
              "value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.challenge }}"
            },
            {
              "name": "geetest_validate",
              "value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.validate }}"
            },
            {
              "name": "geetest_seccode",
              "value": "={{ $(\'Solve GeeTest V3\').item.json.data.solution.seccode }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "fullResponse": false
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        208,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999904",
      "name": "Submit Login Form"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json) }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        512,
        0
      ],
      "id": "99999999-9999-9999-9999-999999999905",
      "name": "Respond to Webhook"
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Fetch GeeTest Challenge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GeeTest Challenge": {
      "main": [
        [
          {
            "node": "Solve GeeTest V3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Solve GeeTest V3": {
      "main": [
        [
          {
            "node": "Submit Login Form",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Submit Login Form": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}

故障排除

"GeeTest V3 访问未找到"

此错误表示您的 CapSolver 账户或计划不包含 GeeTest V3 访问权限。请检查您的 CapSolver 仪表板 以验证您的计划是否包含此服务。

"挑战过期" 或 "挑战无效"

GeeTest V3 challenge 值是动态的,并且会快速过期(通常在 60-120 秒内)。您必须在向 CapSolver 发送解决请求之前立即获取一个新的 challenge。确保您的工作流在每次尝试解决之前都获取了最新的 challenge

"网站 URL 无效" 或 "GT 参数无效"

这些错误表示您在 CapSolver 节点中提供的 websiteURLgt 参数不正确。仔细检查目标站点的开发者工具网络选项卡,以确保您正在使用正确的值。

登录失败,即使 GeeTest V3 已解决

如果 GeeTest V3 成功解决,但登录仍然失败,则可能存在以下问题:

  • 凭据不正确:仔细检查您在登录表单中提交的用户名和密码。
  • 会话不匹配:如果登录过程涉及会话或 cookie,请确保您在获取 GeeTest 挑战和提交登录表单之间保持了相同的会话。
  • 其他表单字段:目标站点可能需要额外的隐藏字段、CSRF 令牌或其他参数才能成功登录。检查表单的 HTML 以识别任何其他必需的字段。
  • 用户代理:某些站点可能会根据用户代理字符串拒绝请求。尝试在 HTTP 请求中设置一个常见的浏览器用户代理。

"CapSolver 凭据无效"

此错误表示您在 n8n 中配置的 CapSolver API 密钥不正确或已过期。请检查您的 CapSolver 仪表板 并更新 n8n 中的凭据。


最佳实践

  1. 始终获取新的挑战:在每次 GeeTest V3 解决尝试之前,始终向目标站点发出 HTTP 请求以获取最新的 challenge 值。挑战会快速过期。
  2. 保持会话:如果目标站点使用会话或 cookie,请确保您在获取挑战和提交表单之间保持了相同的会话。在 n8n 中,您可以使用 HTTP 请求节点来处理 cookie。
  3. 验证参数:仔细检查 gtwebsiteURLchallenge 参数是否正确。这些是 GeeTest V3 解决成功的关键。
  4. 处理错误:在您的工作流中包含错误处理逻辑,以优雅地处理解决失败或登录失败。这可能包括重试机制或通知。
  5. 使用适当的用户代理:在所有 HTTP 请求中设置一个常见的浏览器用户代理字符串,以避免被站点阻止。
  6. 测试和迭代:GeeTest V3 实现可能因站点而异。从小处着手,测试您的工作流,并根据需要进行迭代,以确保其在您的特定目标上可靠运行。
  7. 无需代理:与某些其他验证码类型不同,GeeTest V3 解决通常不需要代理。CapSolver 直接处理挑战。

准备好开始了吗? 注册 CapSolver 并使用奖励代码 n8n 在您的首次充值时获得额外的 8% 奖励!

CapSolver 奖励代码横幅

结论

您已经学习了如何使用 n8n 和 CapSolver 构建 GeeTest V3 解决器 API账户登录自动化工作流

总结:

  • GeeTest V3 的工作原理——它使用交互式谜题,并依赖于静态 gt 和动态 challenge 参数。
  • 如何识别 GeeTest V3 参数——使用开发者工具的网络选项卡来查找 gt 和挑战 API 端点。
  • 动态挑战的重要性——必须在每次解决尝试之前获取新的 challenge 值。
  • 一个解决器 API 端点——接受 GeeTest V3 参数并返回已解决的挑战。
  • 一个账户登录自动化工作流——在提交凭据之前解决 GeeTest V3。
  • 故障排除技巧——处理常见错误,如挑战过期、参数无效和登录失败。
  • 最佳实践——始终获取新的挑战,保持会话,验证参数,并处理错误。

GeeTest V3 的主要复杂性在于其动态的 challenge 参数和三部分解决方案格式。通过在 CapSolver 节点之前添加一个 HTTP 请求节点来获取新的挑战,您可以有效地自动化 GeeTest V3 解决。然后,您可以将这些已解决的令牌无缝集成到您的登录或抓取工作流中。

提示: 这些工作流使用 Webhook 触发器,但您可以将触发器节点替换为任何其他 n8n 触发器——手动、应用程序事件、表单提交等。一旦 GeeTest V3 解决,使用 n8n 的内置节点将结果保存到 Google 表格、数据库、云存储或通过 Telegram/Slack/电子邮件发送警报。


常见问题

什么是 GeeTest V3?

GeeTest V3 是一种行为验证码系统,通过交互式谜题(如滑动拼图、图标点击和单词匹配)来验证用户。它使用一个静态的 gt 参数和一个动态的 challenge 参数,该参数会快速过期。

GeeTest V3 与 GeeTest V4 有何不同?

GeeTest V4 使用不同的 API 结构,例如 captcha_id 而不是 gt,并且不需要单独获取 challenge。本指南专门针对 GeeTest V3。如果您在页面源代码中看到 captcha_id,则表示您正在处理 V4。

解决 GeeTest V3 挑战需要多少钱?

价格因使用情况而异。请查看 CapSolver 定价页面 以了解 GeeTest V3 的当前价格。GeeTest V3 解决任务通常比简单的图像到文本识别更昂贵,但比某些其他复杂的验证码类型更便宜。

解决 GeeTest V3 挑战需要多长时间?

GeeTest V3 解决任务通常需要 10-30 秒,具体取决于挑战的复杂性和 CapSolver 服务器的负载。与 ImageToTextTask 不同,GeeTest V3 解决涉及任务创建和轮询,因此它不是即时返回的。

我需要代理来解决 GeeTest V3 吗?

CapSolver 的 GeeTest V3 解决服务通常不需要您提供代理。CapSolver 会在内部处理代理需求。您只需提供 websiteURLgtchallenge 参数。

为什么我的 challenge 值总是过期?

GeeTest V3 challenge 值是动态的,并且会快速过期(通常在 60-120 秒内)。您必须在向 CapSolver 发送解决请求之前立即获取一个新的 challenge。确保您的工作流在每次尝试解决之前都包含一个 HTTP 请求节点来获取最新的 challenge

如果 GeeTest V3 解决成功但登录仍然失败怎么办?

如果 GeeTest V3 解决成功但登录仍然失败,请检查以下几点:

  • 凭据:确保您提交了正确的用户名和密码。
  • 会话/Cookie:确保您在获取挑战和提交登录表单之间保持了相同的会话和 cookie。
  • 其他表单字段:检查 HTML 表单中是否有任何其他必需的隐藏字段或 CSRF 令牌。
  • 用户代理:尝试在 HTTP 请求中设置一个常见的浏览器用户代理字符串。

我可以在 n8n Cloud 中使用此工作流吗?

是的。此工作流适用于自托管 n8n 和 n8n Cloud。CapSolver 节点已作为官方集成提供——只需添加您的 API 凭据即可。

合规声明: 本博客提供的信息仅供参考。CapSolver 致力于遵守所有适用的法律和法规。严禁以非法、欺诈或滥用活动使用 CapSolver 网络,任何此类行为将受到调查。我们的验证码解决方案在确保 100% 合规的同时,帮助解决公共数据爬取过程中的验证码难题。我们鼓励负责任地使用我们的服务。如需更多信息,请访问我们的服务条款和隐私政策。

更多