框选验证码(把目标框起来)
框选验证码(把目标框起来) 是 通用题型 · 无单一厂商(品牌来源里最常见的是 hCaptcha 的 image_label_area_select 一族) 的框选。一张图配一句指令——「Draw a tight bounding box around the guitar」「把图里的车框出来」——用户按住鼠标在图上拖出一个矩形,把目标物体圈进去。不是点几下,是拖出一个框。
接口规格
| 项目 | 值 |
|---|---|
| type | bounding_box |
| 必填参数 | body |
| 可选参数 | comment |
| 返回 | 一组矩形框(solution.bounding_boxes) |
| 怎么用这个解 | 一组矩形框,每个是 `{x_min, x_max, y_min, y_max}`(像素坐标) |
| 价格 | $1.81 / 1K 次 —— 按成功计费,没解出来退款 |
参数去页面哪里取
下面全部是可以直接照做的定位方法 —— DOM 属性名、JS 全局变量名、script 上的 query 参数。
你要拿两样东西:图片的 base64 和 「要框什么」那句话;拿回来的是你提交的那张图的像素坐标,回填之前几乎总要做一次缩放换算。
取图(按页面上的形态分四种)
· <img>:读 .src。若是 data:image/png;base64,xxxx,只取逗号后面那一段(body 不收 data: 前缀,也不收换行)。若是 URL,要带着同一个 cookie / Referer 去取——这类挑战图常常是一次性、会话绑定的,换个会话再取就是另一张图了。
· <canvas>:canvas.toDataURL('image/png').split(',')[1]。
· CSS 背景图:getComputedStyle(el).backgroundImage 里 url(...) 那段。
· 跨域 iframe(hCaptcha 属于这一类):挑战跑在 https://newassets.hcaptcha.com/captcha/v1/<build>/static/hcaptcha.html 里,父页面读不到它的 DOM,contentDocument 是 null。两条路:用 CDP Page.captureScreenshot 带 clip 截那个 iframe 元素的矩形区域;或者在 Network 里把挑战图的响应体抠出来。Playwright 的话 page.frame_locator(...) 能进去定位元素再 .screenshot()。
取题面(填进 `comment`)
· hCaptcha 的指令文本在挑战 iframe 里的 .prompt-text(图块元素是 .task-image)。
· ⚠⚠ 别对这段文字做朴素字符串匹配:实测抓到的 hCaptcha 提示里混着西里尔同形字——guіtаr 里的 і 是 U+0456(CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I)、а 是 U+0430(CYRILLIC SMALL LETTER A),肉眼是 guitar,text == "guitar" 永远 false。原样透传给识别没问题(读的人和模型照样认得),坏掉的是你自己那层关键词判断;要做判断先过一遍 Unicode confusables 归一。
· 页面上找不到提示语就自己写(comment: "框出所有的车")。⚠ 这个参数不传,识别方无从知道你要什么——这条题型没有默认目标。
把结果用回去
· 返回是一组 {x_min, x_max, y_min, y_max},单位是你提交的那张图的像素,原点在左上角,x 向右、y 向下。
· 换算回页面坐标:const r = img.getBoundingClientRect(); pageX = r.left + x * r.width / img.naturalWidth; pageY = r.top + y * r.height / img.naturalHeight; —— 截图时 deviceScaleFactor / devicePixelRatio 不为 1,或者图被 CSS 缩放显示过,漏掉这一步就是整体偏移。
· 目标站要「画框」时通常是一次拖拽:在 (x_min, y_min) 按下、移动、在 (x_max, y_max) 松开(mousedown / mousemove / mouseup,触屏实现走 pointerdown 系列)。⚠ 中间那几步 mousemove 别省——不少实现会看轨迹。
· 目标站要 JSON 时留意坐标约定:有的接口收 0–1 的归一化比例(除以图宽/图高),有的收 [x, y, w, h](w = x_max - x_min,h = y_max - y_min)。
该用哪条能力的判据:要「拖出一个框」→ 这条;要「依次点几个字 / 几个图标」→ 点选那条,交付的是 {x, y} 点而不是矩形;要「从九宫格里挑出所有含 X 的格子」→ 那是分类不是定位,交付的是格子序号。三者的界面都像「在一张图上作业」,但把框当点提交、或把点当框提交,目标站一律判失败。
调用示例
一个端点解全部验证码类型 —— 换一种验证码只改 type 这一个字段。
curl -X POST https://api.everyinfra.com/api/v1/captcha \ -H "Authorization: Bearer omg_你的KEY" \ -H "Content-Type: application/json" \ -d '{"type":"bounding_box","body":"<body>"}'
{ "solution": { "bounding_boxes": "…" }, "billing": { "charged": true, "credits": 130 }}
怎么确认目标站用的就是它
赌的是「定位」比「分类」难:不只要认出目标是什么,还要给出它在图里的精确矩形范围,容错区间比点一个九宫格格子小得多,也比点一个坐标点更难蒙对。这类题往往同时在收集真实的物体检测标注数据——hCaptcha 把它明确写成商业模式,官网 labeling 页把「Bounding Boxes — Accurate object detection in images and video」列为它对外售卖的标注类型之一。
容易搞混的
最容易和点选验证码混——同样一张图配一句提示,界面几乎一样。区分看交付物:框选要的是一个矩形范围({x_min, x_max, y_min, y_max}),点选要的是若干个坐标点({x, y});框选题要你按住拖动,点选题只要你点一下。其次容易和九宫格图像分类混(reCAPTCHA / hCaptcha 那种「选出所有含红绿灯的格子」)——那个根本不需要定位,交付的是格子序号,是分类不是回归。判断方法最直接:看提示语的动词,「draw / 框 / 圈」是这条,「click / select / 点」是另外两条。
常见部署场景
- hCaptcha 的挑战里(内部任务类型标识是 `image_label_area_select`,子型 `bounding_box`)。实际抓到的提示原文是 `Draw a tight bounding box around the <目标>.`
- hCaptcha 部署面本身很广——它主打 reCAPTCHA 直接替代品,被大量站点当作默认人机验证
- 把「一张图 + 一句『框出 X』」直接摆在页面上的自建/内部图像挑战(小众票务、二手交易、后台审核入口等)。这类没有品牌、没有 sitekey,只有一个 img/canvas 和一句提示 —— 这一条是从题型形态推断的分布,没有单一权威来源
- ⚠ 反例值得记住:reCAPTCHA v2 **没有**画框题。它只有三种——3×3 静态网格分类、3×3 动态刷新、4×4 切块(学术复现文献逐一列出)。在 reCAPTCHA 上看到的一律不是这条能力
已知的坑
body 只收裸 base64:不能带 data:image/png;base64, 前缀,也不能有换行。从 <img>.src 或 canvas.toDataURL() 拿到的字符串必须先切掉逗号前那一段。
comment 不传就没有默认目标——这条题型不像点选那样能从图里自行推断该找什么,不给指令等于让识别方猜。
返回的坐标是提交图的像素,不是页面 CSS 像素。截图 DPR 不为 1、或图片被 CSS 缩放显示,都必须按 naturalWidth/naturalHeight 与 getBoundingClientRect 的比例换算回去。
hCaptcha 的挑战跑在跨域 iframe(newassets.hcaptcha.com)里,父页面拿不到 contentDocument。只能靠截图元素或抓网络响应体取图,别指望 querySelector 穿进去。
hCaptcha 的提示文本里掺西里尔同形字(实测 U+0456 / U+0430),肉眼与拉丁字母无异。原样透传没事,但任何 == / includes() 关键词判断都会静默失效。
挑战图多为一次性、会话绑定:重新请求同一个 URL 往往换成另一张图,而你手里那组坐标只对当时提交的那张图有效。取图和用结果要在同一轮里完成。
别对图做二次压缩、裁剪或缩放后再提交,然后按原图坐标去点。提交什么图就按什么图的坐标系算,两边必须是同一张。
不要把它和点选(points)当成同一件事去混用参数。二者的解形状不同,客户拿到 42 得知道那是「像素范围」还是「一个点」。
与点选验证码不是一回事:那个交付的是几个坐标点,这个交付的是矩形范围
常见问题
框选验证码(把目标框起来) 要传哪些参数?
必填 body;可选 comment。请求里 type 传 bounding_box。
解出来的东西怎么用?
返回一组矩形框,取 solution.bounding_boxes。一组矩形框,每个是 {x_min, x_max, y_min, y_max}(像素坐标)
Page.captureScreenshot 要去页面的哪里找?
重点找 Page.captureScreenshot、deviceScaleFactor、devicePixelRatio。本页「参数去页面哪里取」一节写了全部位置与取法,含可直接粘进控制台的一行命令。
怎么确认目标站用的就是 框选验证码(把目标框起来)?
最容易和点选验证码混——同样一张图配一句提示,界面几乎一样。区分看交付物:框选要的是一个矩形范围({x_min, x_max, y_min, y_max}),点选要的是若干个坐标点({x, y});框选题要你按住拖动,点选题只要你点一下。其次容易和九宫格图像分类混(reCAPTCHA / hCaptcha 那种「选出所有含红绿灯的格子」)——那个根本不需要定位,交付的是格子序号,是分类不是回归。判断方法最直接:看提示语的动词,「draw / 框 / 圈」是这条,「click / select / 点」是另外两条。
有什么容易踩的坑?
body 只收裸 base64:不能带 data:image/png;base64, 前缀,也不能有换行。从 <img>.src 或 canvas.toDataURL() 拿到的字符串必须先切掉逗号前那一段。
多少钱一次,失败扣不扣?
$1.81 / 1K 次。按成功计费 —— 没解出来一律退款,所以失败不花钱。账单按次记,标价按每千次是为了让量级读得出来。