Files
dsh_ai1net_server/归档/skills-清理-20261007/web-fetch-antibot/SKILL.md
T
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次)
- .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…),
  目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪
- .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/)
- .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*)
- .gitignore 补:备份件(*.bak-*)
- 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

6.4 KiB
Raw Blame History

name, description, version, updated_at, agent_created
name description version updated_at agent_created
web-fetch-antibot 网页抓取遇到反爬(JS 渲染壳页、一次性令牌、人机验证页)时的判断与止损方法。当出现以下情形时触发:WebFetch 返回空或 fetch failed、curl 拿到的 HTML 里目标内容一个字符都没有、正文代理返回"unusual traffic / verify you are human"、无头浏览器被踢到 /sorry/ 或 /cdn-cgi/challenge-platform/、用户给出 share.google/aimode/* 或类似"分享链接"。核心 = 三个判据快速归因 + 硬止损规则(同一 URL 换 2 种方式失败即停手,改向用户索取原文),避免在无解目标上烧掉工具预算。 1.0.0 2026-09-19 true

web-fetch-antibot — 反爬页面的归因与止损

抓不到网页时,问题通常不在"网络通不通",而在页面属于哪一类。本技能给的是判断顺序和何时停手,不是"再多试几种 UA"。

一、先分类,再动手(三层判据)

按顺序做,命中即停在该层、按该层处置。

判据 A — JS 渲染壳页(最有价值的一条)

curl -sL -o page.html -w "%{http_code} %{size_download}\n" <URL>
grep -c "<目标关键词>" page.html      # 期望 >0
grep -o "<title>[^<]*</title>" page.html
  • 关键词计数 = 0 且 size_download 不小(几十 KB 以上)⇒ 壳页,正文由前端 XHR 现拉。
  • 附带特征:<title> 是通用名(Google Search、Just a moment...)、无 AF_initDataCallback / __NEXT_DATA__ / window.__INITIAL_STATE__ 这类结构化内联数据、脚本是混淆过的自解压串。
  • 处置:换 UA / 换 Googlebot UA 无用(实测过,字节数只差几百,命中数仍为 0)。直接进判据 B。

判据 B — 无头浏览器能否过

agent-browser open <URL> ; agent-browser wait 15000 ; agent-browser get url
  • 落在 /sorry/index、/cdn-cgi/challenge-platform/、/httpservice/retry/enablejs ⇒ 人机验证或 JS 强制。
  • 一手经验:headless 基本无解。navigator.webdriver、CDP 注入痕迹、WebGL / 字体指纹在 Google、Cloudflare 侧是一等信号,不是靠 --headed 或换 UA 能绕的。
  • 注意首启成本:冷启 30–45 s,前台直跑会撞超时 ⇒ 后台跑 + sleep 后读文件;收尾务必 agent-browser close --all。

判据 C — 正文代理(r.jina.ai 等)返回什么

  • 返回验证页原文(含 unusual traffic、verify you are human、About this page)⇒ 说明是 IP / 指纹级拦截,不是渲染问题 ⇒ 代理路线也废。
  • 顺带信息:Jina 的返回里会带它自己的出口 IP(实测 2600:1900:0:4006::f01,Google Cloud 段)—— 数据中心 IP 本身就是降权因子。

二、硬止损规则(本技能的主要价值)

同一 URL 换 2 种方式仍未拿到正文 ⇒ 停手,直接向用户索取"粘贴原文"。

来源:2026-09-19 一个 share.google/aimode/* 链接,试了 6 条路全部失败(WebFetch / curl 直连 / curl 经代理 / curl 换 Googlebot UA / r.jina.ai / 无头 Chromium),累计十余次工具调用,最终仍然只能请用户粘贴。换 UA 和换客户端的边际收益在这个组合面前是 0。

允许的例外:待抓页是你自己项目的(有凭据 / 有源站),那属于部署问题不是反爬问题,另走排障。

三、本机环境陷阱(沙箱内必踩,会伪装成"网络不通")

  • 沙箱会注入 HTTPS_PROXY=127.0.0.1:63854,那是沙箱内代理,对 Google 返回 502 CONNECT tunnel failed。
  • 沙箱内 curl https://www.google.com 返回 000,不代表网络不通。
  • 需要真实外网时:dangerouslyDisableSandbox: true + 显式指定用户自己的代理 HTTPS_PROXY=http://127.0.0.1:10800(与 git config --global http.proxy 同值)。
  • 沙箱内 PATH 被 shim 重置 ⇒ 用完整 POSIX 路径 /e/ProgramData/.workbuddy/binaries/PortableGit/versions/1.2.0/usr/bin。
  • agent-browser 若报 command not found:装到托管 Node 下 —— npm install -g agent-browser(用 E:\ProgramData\.workbuddy\binaries\node\versions\22.22.2-3);Chrome 本体插件已预先下到 ~/.agent-browser/browsers/。

四、案例锚点:Google AI Mode(Gemini)分享链接

技术链路(逐跳实测):

https://share.google/aimode/<id>
  302 → https://www.google.com/share.google?q=aimode/<id>
  301 → https://www.google.com/search?smstk=<token>&smstidx=3&q=<urlencoded>&udm=50
        &csuir=1&aep=34&kgs=<hash>&shem=...&shndl=37&shmd=<hash>&source=sh/x/aim/m1/1

四道反爬叠加:

  1. JS 渲染 — 落盘 HTML 92,262 B,目标中文关键词出现 0 次,无数据结构化回调。
  2. 一次性令牌 — smstk / smstidx 与会话绑定,重放即失效。
  3. 无 JS 兜底 = 元刷新 — <noscript><meta content="0;url=/httpservice/retry/enablejs?sei=...">。
  4. 边缘人机验证 — 真浏览器被踢到 /sorry/index?continue=...。

唯一能免费拿到的信息:URL 的 q= 参数原文暴露了提问内容(本次解出「区块链 二级链技术发展的如何了」)。所以拿到这类链接时,先把 q= 解码出来,至少能知道用户想问什么;正文再请用户粘贴。

同类站点的同族特征:udm=50 = Google AI Mode;smstk 前缀 = 分享态令牌;Cloudflare 的对应物是 /cdn-cgi/challenge-platform/ + cf_clearance cookie。

五、正确交付姿势

抓不到不是失败,说不清"为什么抓不到"才是失败。向用户报告时必须给出:已试过哪几条路、每条路的具体返回(状态码 / 字节数 / 命中数)、归因到哪一层、以及"你这边的可用替代动作"(粘贴原文 / 提供导出文件 / 给带凭据的访问方式)。

六、复用的工具账本

路线 适用 本案例结果
WebFetch 静态 HTML fetch failed(空)
curl 直连 静态 HTML / API 502(沙箱内代理)
curl -x 用户代理 静态 HTML 200 但壳页,命中 0
curl + Googlebot UA 怕被 UA 拦的站 200 但壳页,命中 0
r.jina.ai 正文代理 中等强度 JS 站 返回反爬验证页
agent-browser 无头 真需要渲染 / 交互 落到 /sorry/index

顺序建议:WebFetch → curl 落盘 + 关键词计数 →(判据 A 命中则直接问用户)→ 只在"确实是 JS 渲染但无强验证"时才上无头浏览器。