- 变更规模:新增 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/ 知识文件,按口径入库)
6.4 KiB
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
四道反爬叠加:
- JS 渲染 — 落盘 HTML 92,262 B,目标中文关键词出现 0 次,无数据结构化回调。
- 一次性令牌 —
smstk/smstidx与会话绑定,重放即失效。 - 无 JS 兜底 = 元刷新 —
<noscript><meta content="0;url=/httpservice/retry/enablejs?sei=...">。 - 边缘人机验证 — 真浏览器被踢到
/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 渲染但无强验证"时才上无头浏览器。