樱花动漫 文档
返回官网 GitHub
本站为 Kazumi 官方文档站的克隆参考站,内容整理自开源项目,仅作学习与参考;本应用规则格式完全兼容 Kazumi。

人机验证应对

本文面向规则作者,讲解当目标站在搜索 / 访问阶段被人机验证拦截时,如何用规则根级的 antiCrawlerConfig 应对。反爬配置挂在规则根级,仅在 XPath 搜索阶段被验证页替代时生效。【skill 资料】官方文档原文称:「反反爬虫:用于 XPath 搜索响应被验证页替代的情况。应根据网站实际验证方式配置检测条件和交互步骤。」

标注约定

本文沿用资料标注:【官方原文】引自 Kazumi 官方文档;【skill 资料】引自随附的规则校验器 / 探测脚本实现;【fork 源码】引自樱花动漫 fork 应用源码(属本 App 扩展行为,官方规则模型没有);【经验】为调试实践补充,非官方原文。

一、先判断:被拦后到底是哪一类页面

动手配 antiCrawlerConfig 之前,必须先用浏览器(或 curl)实际访问目标站的搜索地址,看清被拦后返回的到底是什么页面,再决定走哪一档,严禁套模板:

  1. 普通图片验证码页:返回的不是结果列表,而是一张图形验证码 <img> + 一个输入框 + 一个提交按钮,需要人工(或打码服务)辨认字符后提交。→ 见下文第 1 档。
  2. 点击 / 滑块 / 行为验证页:一个「点击按钮继续 / 我不是机器人」的过渡页,或滑块拼图、点选文字等行为验证。→ 见下文第 2 档(注意:真滑块拼图 / 点选 / 行为验证并不能自动解)。
  3. Cloudflare CF / Akamai 等智能风控页:出现 “Just a moment…”、challenge、Ray ID、Akamai Bot Manager 等字样,需要 JS 执行甚至真实浏览器环境才能放行。→ 见下文第 3 档,常需配合根级 useWebview。
  4. 只是登录拦截:没有任何验证交互,只是 302 跳到登录页 / 弹窗登录。这不属于人机验证,应走 需要登录后才能观看(配 needLogin / loginURL),而不是开 antiCrawlerConfig。
NOTE

【经验】「搜索结果为空 / searchList 匹配 0 条」不一定是 XPath 写错了——很可能是搜索响应被 302 到了登录页或验证页。先判断「被谁拦了」,再决定配登录还是配反爬。

二、三档对照总表(核心)

【fork 源码 / skill 资料】按 MCP 档位映射口径,三档与 captchaType 的对应关系如下。无论哪一档,antiCrawlerConfig 对象都必须完整给出(带 enabled 等全部字段),不能只写一个数字。

档位典型拦截页面配置必配配套字段能否自动过
第 1 档
普通图片验证码
搜索返回图形验证码页:验证码图片 + 输入框 + 提交按钮 captchaType: 1
(即常说的 antiCrawlerConfig=1)
captchaImage / captchaInput / captchaButton(均为 XPath)+ 检测字段 captchaDetectType / captchaDetectValue 半自动:应用展示图片,人工或打码服务输入后提交
第 2 档
点击 / 滑块 / 行为验证
「点一下继续 / 我不是机器人」过场页,或滑块拼图、点选、行为验证 captchaType: 2(自动点击) captchaButton(放行按钮 XPath)+ captchaDetectType / captchaDetectValue 仅对「点一下放行」的轻量过场有效;真滑块拼图 / 点选 / 行为验证无法自动解,建议换源或手动配合
第 3 档
CF / Akamai 智能风控
Cloudflare CF、Akamai 等智能风控 / JS challenge 页 captchaType: 3(自定义 JS captchaScript),必要时配合根级 useWebview: true captchaScript(页面内执行的 JS)+ 检测字段;useWebview 走真实浏览器内核 CF Turnstile 等强挑战一般无法自动过,建议换源或改用公开 JSON 接口
WARNING

【经验】不要为了省事只写 "antiCrawlerConfig": 1。校验器要求 antiCrawlerConfig 是一个完整对象(含 enabled 等全部字段),单独给数字不会被识别。下面每个示例都是完整可抄的对象。

三、字段总表

【skill 资料】字段名以规则校验器 kazumi_rule_codec.ts 的实际实现为准(注意:验证方式字段叫 captchaType,不叫 mode):

字段类型含义
enabledbool是否启用反爬配置
captchaTypeint (1/2/3)验证方式:1=图片验证码,2=自动点击,3=自定义 JS
captchaDetectTypeint (1/2/3)拦截检测方式:1=XPath 检测节点存在,2=文本匹配,3=正则匹配
captchaDetectValuestring检测表达式 / 特征文本 / 正则
captchaImagestring (XPath)图片验证码图片节点定位(仅第 1 档用)
captchaInputstring (XPath)验证码输入框节点定位(仅第 1 档用)
captchaButtonstring (XPath)提交 / 放行按钮节点定位(第 1、2 档用)
captchaScriptstringcaptchaType=3 时在页面 WebView 上下文执行的自定义 JS

校验器硬性约束:captchaType 与 captchaDetectType 只能取 1、2、3,否则报 must be 1, 2, or 3。

四、检测方式:captchaDetectType 怎么选

应用靠 captchaDetectType + captchaDetectValue 判断「这次搜索响应是不是被验证页替换了」。三种检测方式:

  • captchaDetectType: 1 —— XPath 节点存在:captchaDetectValue 写一个 XPath(如 //form[@id='captcha-form'] 或 //div[@id='check-wrap'])。页面中存在该节点即判定为被拦截。
  • captchaDetectType: 2 —— 文本匹配:captchaDetectValue 写一段特征文字(如 请输入验证码)。响应页面包含这段文字即判定为被拦截。
  • captchaDetectType: 3 —— 正则匹配:captchaDetectValue 写一个正则(如 challenge\.js|安全验证)。页面 HTML 命中该正则即判定为被拦截。
NOTE

【经验】检测条件要挑「正常结果页里绝不会出现、只有验证页才有」的特征:一个专属容器 id、一句固定文案、一个固定脚本文件名,都比宽松关键词可靠,避免正常页被误判成拦截。

五、三档完整可抄 JSON 示例

第 1 档:captchaType = 1(普通图片验证码)

适用场景:搜索请求返回带图形验证码的页面,需要展示图片、人工(或接打码服务)输入后提交。

{
  "api": "1",
  "type": "anime",
  "name": "示例图片验证码站点",
  "version": "1.0",
  "baseURL": "https://captcha-demo.example.com/",
  "searchURL": "https://captcha-demo.example.com/search?wd=@keyword",
  "searchList": "//div[@class='search-item']",
  "searchName": "//h3/a",
  "searchResult": "//h3/a",
  "chapterRoads": "//div[@class='playlist-box']",
  "chapterResult": "//ul/li/a",
  "searchMode": "xpath",
  "chapterMode": "xpath",
  "antiCrawlerConfig": {
    "enabled": true,
    "captchaType": 1,
    "captchaDetectType": 2,
    "captchaDetectValue": "请输入验证码",
    "captchaImage": "//img[@id='captcha_img']",
    "captchaInput": "//input[@name='captcha']",
    "captchaButton": "//button[@id='submit_btn']",
    "captchaScript": ""
  }
}
  • captchaDetectType: 2 + captchaDetectValue: "请输入验证码" 表示:搜索响应页面包含「请输入验证码」这段文字时,判定为被拦截。
  • 命中拦截后,应用用 captchaImage 取出验证码图片展示出来,等用户输入后填入 captchaInput,再点击 captchaButton 提交。
  • 检测也可换成 captchaDetectType: 1(此时 captchaDetectValue 写 XPath)或 captchaDetectType: 3(写正则)。

第 2 档:captchaType = 2(自动点击)

适用场景:拦截页只是一个「点击按钮继续 / 我不是机器人」的过渡页,不需要输入字符,自动点一下按钮就能放行。

{
  "api": "1",
  "type": "anime",
  "name": "示例点击验证站点",
  "version": "1.0",
  "baseURL": "https://click-demo.example.com/",
  "searchURL": "https://click-demo.example.com/search?wd=@keyword",
  "searchList": "//div[@class='search-item']",
  "searchName": "//h3/a",
  "searchResult": "//h3/a",
  "chapterRoads": "//div[@class='playlist-box']",
  "chapterResult": "//ul/li/a",
  "searchMode": "xpath",
  "chapterMode": "xpath",
  "antiCrawlerConfig": {
    "enabled": true,
    "captchaType": 2,
    "captchaDetectType": 1,
    "captchaDetectValue": "//div[@id='check-wrap']",
    "captchaImage": "",
    "captchaInput": "",
    "captchaButton": "//button[@id='pass-check']",
    "captchaScript": ""
  }
}
  • captchaType: 2 时不需要 captchaImage / captchaInput,只需要把 captchaButton 指向那个「放行」按钮。
  • 检测条件这里用 captchaDetectType: 1(XPath 节点存在):页面出现 #check-wrap 过场容器时,自动点击 #pass-check。
WARNING

【经验】自动点击只对「点一下就放行」的轻量过场有效;对真正的滑块拼图、点选文字、行为轨迹验证等强人机验证无效——那种站点建议换源,或在规则说明里标注需要用户手动配合,不要硬刚。

第 3 档:captchaType = 3(自定义 JS)

适用场景:拦截页需要执行一段页面内脚本(比如调用页面自带的 JS 函数、操作 cookie、跳转特定 URL)才能放行;Cloudflare CF、Akamai 等智能风控站一般走这一档。

{
  "api": "1",
  "type": "anime",
  "name": "示例JS验证站点",
  "version": "1.0",
  "baseURL": "https://jscheck-demo.example.com/",
  "searchURL": "https://jscheck-demo.example.com/search?wd=@keyword",
  "searchList": "//div[@class='search-item']",
  "searchName": "//h3/a",
  "searchResult": "//h3/a",
  "chapterRoads": "//div[@class='playlist-box']",
  "chapterResult": "//ul/li/a",
  "searchMode": "xpath",
  "chapterMode": "xpath",
  "antiCrawlerConfig": {
    "enabled": true,
    "captchaType": 3,
    "captchaDetectType": 3,
    "captchaDetectValue": "challenge\\.js|安全验证",
    "captchaImage": "",
    "captchaInput": "",
    "captchaButton": "",
    "captchaScript": "document.cookie='pass=ok;path=/';location.reload();"
  }
}
  • captchaType: 3 时,命中拦截后应用在该页面 WebView 上下文里执行 captchaScript 这段 JS。
  • 这里 captchaDetectType: 3 是正则匹配,页面 HTML 里出现 challenge.js 或「安全验证」字样即触发。
  • 【经验】脚本怎么写取决于站点拦截页的实际逻辑:常见套路是种一个放行 cookie 后 location.reload(),或调用页面已有的验证函数。拿不准的 API 就先在浏览器 Console 里手工跑通再抄进来。
DANGER

【经验 / 官方原文】CF Turnstile、Akamai Bot Manager 这类带前端加密 + 行为检测的强挑战,一般无法靠一段 captchaScript 自动过。官方文档明确建议:遇到这类无法复现的前端加密 / 强验证,应「优先选择结构更稳定、无需复杂验证的来源,或改用其公开 JSON 接口」。

六、useWebview:什么时候要开

【fork 源码】useWebview 是规则根级的布尔字段(不在 antiCrawlerConfig 内部),规则模板里常见写法是 "useWebview": true。它的作用是让该规则的页面请求走真实 WebView 浏览器内核,而不是纯 HTTP 拉 HTML——对依赖 JS 渲染、或带智能风控的站点有效。

  • 普通 XPath 站(服务端直接吐 HTML)不需要开 useWebview,纯请求 + XPath 更快更省。
  • 第 3 档的 CF / Akamai 等智能风控站,常需要 captchaType: 3 配 useWebview: true:用真实浏览器内核加载拦截页,再在其上下文执行 captchaScript,才有机会种下放行 cookie / 跑完 challenge 跳转。
NOTE

【经验】开 useWebview 会让搜索 / 加载变慢、更耗资源,只在「不开就被风控页挡住、且确实验证逻辑能被 captchaScript 或真实内核跑通」时才用。CF Turnstile 这类强挑战即便开了 WebView 也多半过不去,优先换源 / 公开接口,不要硬刚。

根级示意(与 antiCrawlerConfig 并列,不嵌套):

{
  "api": "1",
  "type": "anime",
  "name": "示例真实浏览器内核站点",
  "version": "1.0",
  "baseURL": "https://webview-demo.example.com/",
  "useWebview": true,
  "searchMode": "xpath",
  "chapterMode": "xpath",
  "antiCrawlerConfig": {
    "enabled": true,
    "captchaType": 3,
    "captchaDetectType": 3,
    "captchaDetectValue": "challenge\\.js|安全验证",
    "captchaImage": "",
    "captchaInput": "",
    "captchaButton": "",
    "captchaScript": "document.cookie='pass=ok;path=/';location.reload();"
  }
}

七、关闭反爬配置:骨架保留不要删

不需要反爬时保留默认骨架即可(enabled: false,其余字段空串),不要整段删掉——完整规则骨架里始终带这个对象:

"antiCrawlerConfig": {
  "enabled": false,
  "captchaType": 1,
  "captchaImage": "",
  "captchaInput": "",
  "captchaButton": "",
  "captchaDetectType": 1,
  "captchaDetectValue": "",
  "captchaScript": ""
}

八、常见坑(与验证码相关)

  1. captchaType 不是 mode:字段名是 captchaType,检测类型是 captchaDetectType,两个都只能取 1/2/3。写成 "mode": 1 校验器不认。
  2. 验证码图片用 XPath 定位,不要手写图片 URL:captchaImage 填的是指向验证码 <img> 节点的 XPath,由应用在 WebView 里取出展示,不需要你在 JSON 里手写图片 URL。
  3. curl 调试验证码要带会话 Cookie:验证码图片通常和验证页面共享同一个会话 Cookie。直接 curl -O 图片地址而不带刚才拿到的 Cookie,拿到的是另一张图,永远对不上。
  4. 反爬配置只对 XPath 搜索阶段生效:antiCrawlerConfig 管的是「搜索那一下」被验证页替换的情况;选集阶段、播放页阶段被拦,它管不到。API 模式的请求被 403 / 拦截,要去补 API 请求 request.headers 里的 Referer / UA / Cookie,而不是去开 antiCrawlerConfig。
  5. 强人机验证不要硬刚,优先换源:滑块拼图、点选文字、Cloudflare Turnstile 等强验证,自动点击 / 一段 JS 基本解不开,优先选择结构更稳定、无需复杂验证的来源,或改用其公开 JSON 接口写 API 规则;实在无法自动处理时,在规则说明中标注需要用户手动配合。

相关文档

依据

本节依据樱花动漫 fork 规则模型(antiCrawlerConfig 校验器实现、三档映射口径)与 Kazumi 官方规则文档(XPath 规则开发、API 规则开发,官方来源)整理;标注为经验的条目来自规则调试实践,非官方原文。

樱花动漫 · 基于 Flutter · 开源 GPL-3.0 · 规则格式兼容 Kazumi