人机验证应对
本文面向规则作者,讲解当目标站在搜索 / 访问阶段被人机验证拦截时,如何用规则根级的 antiCrawlerConfig 应对。反爬配置挂在规则根级,仅在 XPath 搜索阶段被验证页替代时生效。【skill 资料】官方文档原文称:「反反爬虫:用于 XPath 搜索响应被验证页替代的情况。应根据网站实际验证方式配置检测条件和交互步骤。」
本文沿用资料标注:【官方原文】引自 Kazumi 官方文档;【skill 资料】引自随附的规则校验器 / 探测脚本实现;【fork 源码】引自樱花动漫 fork 应用源码(属本 App 扩展行为,官方规则模型没有);【经验】为调试实践补充,非官方原文。
一、先判断:被拦后到底是哪一类页面
动手配 antiCrawlerConfig 之前,必须先用浏览器(或 curl)实际访问目标站的搜索地址,看清被拦后返回的到底是什么页面,再决定走哪一档,严禁套模板:
- 普通图片验证码页:返回的不是结果列表,而是一张图形验证码
<img>+ 一个输入框 + 一个提交按钮,需要人工(或打码服务)辨认字符后提交。→ 见下文第 1 档。 - 点击 / 滑块 / 行为验证页:一个「点击按钮继续 / 我不是机器人」的过渡页,或滑块拼图、点选文字等行为验证。→ 见下文第 2 档(注意:真滑块拼图 / 点选 / 行为验证并不能自动解)。
- Cloudflare CF / Akamai 等智能风控页:出现 “Just a moment…”、challenge、Ray ID、Akamai Bot Manager 等字样,需要 JS 执行甚至真实浏览器环境才能放行。→ 见下文第 3 档,常需配合根级
useWebview。 - 只是登录拦截:没有任何验证交互,只是 302 跳到登录页 / 弹窗登录。这不属于人机验证,应走 需要登录后才能观看(配
needLogin/loginURL),而不是开antiCrawlerConfig。
【经验】「搜索结果为空 / 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 接口 |
【经验】不要为了省事只写 "antiCrawlerConfig": 1。校验器要求 antiCrawlerConfig 是一个完整对象(含 enabled 等全部字段),单独给数字不会被识别。下面每个示例都是完整可抄的对象。
三、字段总表
【skill 资料】字段名以规则校验器 kazumi_rule_codec.ts 的实际实现为准(注意:验证方式字段叫 captchaType,不叫 mode):
| 字段 | 类型 | 含义 |
|---|---|---|
enabled | bool | 是否启用反爬配置 |
captchaType | int (1/2/3) | 验证方式:1=图片验证码,2=自动点击,3=自定义 JS |
captchaDetectType | int (1/2/3) | 拦截检测方式:1=XPath 检测节点存在,2=文本匹配,3=正则匹配 |
captchaDetectValue | string | 检测表达式 / 特征文本 / 正则 |
captchaImage | string (XPath) | 图片验证码图片节点定位(仅第 1 档用) |
captchaInput | string (XPath) | 验证码输入框节点定位(仅第 1 档用) |
captchaButton | string (XPath) | 提交 / 放行按钮节点定位(第 1、2 档用) |
captchaScript | string | captchaType=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 命中该正则即判定为被拦截。
【经验】检测条件要挑「正常结果页里绝不会出现、只有验证页才有」的特征:一个专属容器 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。
【经验】自动点击只对「点一下就放行」的轻量过场有效;对真正的滑块拼图、点选文字、行为轨迹验证等强人机验证无效——那种站点建议换源,或在规则说明里标注需要用户手动配合,不要硬刚。
第 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 里手工跑通再抄进来。
【经验 / 官方原文】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 跳转。
【经验】开 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": ""
}八、常见坑(与验证码相关)
captchaType不是mode:字段名是captchaType,检测类型是captchaDetectType,两个都只能取 1/2/3。写成"mode": 1校验器不认。- 验证码图片用 XPath 定位,不要手写图片 URL:
captchaImage填的是指向验证码<img>节点的 XPath,由应用在 WebView 里取出展示,不需要你在 JSON 里手写图片 URL。 - curl 调试验证码要带会话 Cookie:验证码图片通常和验证页面共享同一个会话 Cookie。直接
curl -O图片地址而不带刚才拿到的 Cookie,拿到的是另一张图,永远对不上。 - 反爬配置只对 XPath 搜索阶段生效:
antiCrawlerConfig管的是「搜索那一下」被验证页替换的情况;选集阶段、播放页阶段被拦,它管不到。API 模式的请求被 403 / 拦截,要去补 API 请求request.headers里的 Referer / UA / Cookie,而不是去开antiCrawlerConfig。 - 强人机验证不要硬刚,优先换源:滑块拼图、点选文字、Cloudflare Turnstile 等强验证,自动点击 / 一段 JS 基本解不开,优先选择结构更稳定、无需复杂验证的来源,或改用其公开 JSON 接口写 API 规则;实在无法自动处理时,在规则说明中标注需要用户手动配合。
相关文档
- 需要登录后才能观看 —— 被拦只是要求登录(而非人机验证)时,配
needLogin/loginURL。 - XPath 规则开发 ——
antiCrawlerConfig生效的 XPath 搜索阶段与字段基础。
本节依据樱花动漫 fork 规则模型(antiCrawlerConfig 校验器实现、三档映射口径)与 Kazumi 官方规则文档(XPath 规则开发、API 规则开发,官方来源)整理;标注为经验的条目来自规则调试实践,非官方原文。
樱花动漫 · 基于 Flutter · 开源 GPL-3.0 · 规则格式兼容 Kazumi