我给自己写的工具,连着骗了我七次

那天下午我在干一件很琐碎的事:把一篇文章发到公众号和掘金。

草稿早就存好了,正文、图片、摘要都齐了,就差把封面传上去。封面那一步要点系统的文件选择框,鼠标键盘都够不着,只能走 Chrome 的调试协议把文件塞进去。

我那个脚本里有个现成的子命令干这件事。几行代码。写的时候顺手,注释里还标了「已验证」。

那天下午我第一次真正跑它。它报错了。

那一刻我才反应过来,那个「已验证」验的是什么------验的是语法没错、子命令注册上了。真正跑一次上传,一次都没有。

那天我一整天都在被自己的工具骗

往前捋捋,从头一天下午到晚上,我一共踩了七次。它们的共同点不是复杂,是都不报错。

最轻的一次是查封面。我写脚本判断封面传上去没有,脚本说没有------hasImg: false,零张图。我正打算去改数据结构,因为我记得传过。截了个图一看,封面好好地挂在右上角。

问题出在我查错了地方。真正存封面的是一块区域的背景图,不是 <img> 标签。查 <img> 当然查不到。这不算难查,难的是在我改数据结构之前,没人告诉我「你查的那儿压根不可能有图」。

第二次是摘要。字数计数器那儿显示 52/120,我一看还剩一半富余,正准备往里加两句。真实数字是 118/120,只剩两个字的空间。那个 52 是从手机预览的 iframe 里读的,读的是个副本。

第三次最气人。粘完正文,手机预览面板里完完整整一篇,段落、配图、标题全在,看着就是成了。实际正文编辑器里是空的。那个面板是预览,它先给你渲染一份候选副本,让人以为已经进去了。

后面还有三次,一次比一次贵。封面弹窗里四个按钮,用 getElementById 一个都查不到------它们是 class 不是 id。改视口尺寸的那个调试命令,返回一个空对象,看着像成功,其实什么都不干,因为它绑在连接会话上,而我这个脚本每条命令都重开一次连接。表格更离谱,草稿里两个表格老老实实躺在那儿,一发表,全变成了一段段文字,因为编辑器在保存的时候会拿富文本反推 Markdown,而它不认识表格。

这七次里,真正让我停下来想了一会儿的,是最后那次。

我以为我在验证,其实在演

出错之后我回头去查代码,才看到问题在哪儿:这个脚本的底层,每执行一条命令就新开一个连接。而浏览器调试协议里用来定位元素的编号,不是拿到就能用的------你得先在当前这条连接上把文档上下文建起来。

所以我原来那三行代码,第一步建上下文、取到编号,第二步换了一条新连接,拿这个编号去查元素。新连接上还没建上下文,那个编号就用不了。

修法不复杂。但让我在原地停了一会儿的是另一件事:

我为什么要给一个从没跑过的命令标「已验证」?

不是手滑。当时的判断链是这样的:这个命令能正常解析,参数能注册进去,报错信息也写得清楚------一个写对了一半的东西,看起来和跑通没什么区别。

更要命的是时间差。那个「已验证」是我自己在同一个下午写上去的,隔了几个小时,它第一次真跑。第一次跑就报错。

至于为什么这几个小时里没人发现:整个项目写了八个月,同一件事我早就验证过很多次了,只不过验证的是手动那条路 ------点「从图片库选择」,右上角「上传文件」,系统弹框,手动选。每次都成功。setfile 是我为了省掉这几下点击另外加的。

那条路确实成功。所以我给它盖的章,验的是别的东西。一个不会自己叫的坏东西,比一个会叫的坏东西安全得多,也危险得多。

后来的事更难堪

当天晚上我还在这个家目录里 git init 了。不是在项目目录里,是在上一级。

家目录里有什么,我大概知道:几个云厂商的密钥目录、SSH 的配置、各家 CLI 存 token 的文件。git init 也确实成功了,它从来不问你要不要。

真正提交之前我才想起这事,那时候还没 commit,风险是零。我给自己写了一份忽略规则,用的是「先全挡、再放行要提交的那一个目录」------后来知道,靠逐条列黑名单是挡不住的,你总会漏一条。

然后我装了个专门扫密钥的工具去扫。它在我自己的脚本目录里翻出两个文件,里面硬编码了带签名的图片地址。那种地址谁拿到都能用。

那两个文件是我前两天自己写的探针,作用是把图片塞进编辑器。我写它们的时候,只想着「先跑通」,没想过它会被谁看到------我以为没人看的东西,和会被提交的东西,是同一个目录。

现在我的做法很笨

第一,截图才算数。页面上看不见的东西,我就不当它存在。hasImg: false 这种结论,配一张截图一起看。

第二,从服务端读回来才算数。编辑器里显示存好了不算,重新开一个标签,看服务器到底收没收。

第三,写完一个命令,立刻拿一个真数据跑一遍。不用假数据,不用「应该可以」。

这三条都很慢,比以前慢很多。但慢的代价我能看见。

我还在想第四条,暂时没想明白。可能是:别让自己写的工具,成为你最信任的那个。 我对它没有戒心,因为它是我写的,我清楚每一行。这恰恰是问题------陌生工具的毛病我会怀疑,自己写的不会。

写下来主要是给自己看

这篇东西没什么实用价值,教程里不会这么讲。但我今天下午损失的时间,够我把工具重写一遍。

如果别人也遇到过类似的事------自动化跑完了,界面看着没问题,隔几天才发现某一步从来没生效过------那至少说明不止我一个人会这样。

附:本文引用

一、官方文档只说了一半

第二节里那个技术解释,我原来写的是「那个编号只在当前连接里有效 」。 写这篇的时候我去查了官方规范,想给它找个出处------没找到。

Chrome DevTools Protocol 官方规范(devtools-protocol 仓库的 browser_protocol.json, 2026-10-13 取,1,419,927 字节)里,NodeId 的定义全文就一句:

Unique DOM node identifier.

没有「会话」,没有「仅在当前连接内有效」,什么限定都没有。 引一句没说的话,那不叫引用,叫编。 所以那句话我拿不出处,也就不该那么写。

二、我自己测了一遍,测出来我原来的说法是错的

既然文档证明不了,那就测。实验在 experiments/nodeid-scope/, 脚本、原始输出、每一版翻车都在里面。

四臂:

臂 / 做什么 / 结果

  • A ------ 会话 A 取编号 → A 内自查可用 → 断开 → 会话 B 直接用 ------ ✗ 失败
  • B(阳性对照) ------ 会话 B 自己建上下文取编号,同会话内用 ------ ✓
  • C(反向自测) ------ 编一个编号 999999999 ------ ✗ 同样失败
  • D(补漏) ------ 新会话先建上下文 ,再 用 A 留下的旧编号 ------ ⚠️ 成功了

两个会话取到的编号数值都是 1。

D 臂推翻了 A 臂:只要新连接先把文档上下文建起来,A 留下的那个编号照样能用。

所以真实机制是------不是「编号跨会话就死」,是「你这条连接还没建上下文」 。 我原来那三行代码的毛病,是跳过了建上下文就直接用编号, 不是「每条命令重开连接」这件事本身有多严重。

顺带一提,修法也跟着变。我原文写的是「三步串在同一个连接里做完」------ 测完才发现每步各自先建一次上下文也能work,我当时那个「必须串起来」的紧张, 多半也是猜的。

三、这个实验的第一版也骗了我

第一版只有 A/B/C 三臂,结论是「跨会话失效,坐实」,我很满意。

是 D 臂把它推翻的。问题出在阳性对照上:A 臂和 B 臂取到的编号数值相同(都是 1), 而 B 臂自己先建了上下文------等于替 A 臂把那个 1 准备好了。 于是 A 臂的失败被我很自然地读成「跨会话失效」,实际是「没先准备」。

这跟这篇讲的是同一件事:一个不会自己叫的坏东西,比一个会叫的坏东西安全得多, 也危险得多。 我那个实验里,「对照」是有的,只是没跟实验组对齐, 对齐不好的时候,对照组会替实验组把准备工作做完。

四、本文没有引用学术文献

这篇没有做文献综述,也没有引用任何论文或书籍。 第二节那个技术问题我查的是协议规范和实测,不是文献。 写清楚是为了避免读者以为我做过文献工作。

五、取到的 / 没取到的

来源 / 状态

  • CDP 官方规范 browser_protocol.json ------ 取到,但它证明不了我原来那句话
  • devtools-protocol 仓库的 pdl/DOM.pdl ------ 两个分支(master / main)均 404
  • chromedevtools.github.io 的 HTML 页 ------ 只是重定向壳,内容在 JS 里,正文取不到

没有取到的东西我列在这儿,不用记忆去补。

相关推荐
sun_weitao1 小时前
Chrome 扩展插件开发指南
前端·javascript·chrome
咧咧小侠1 天前
Windows Codex 连接 Chrome 失败:一次 nodeRepl.fetch 报错排查记录
前端·chrome
疯狂敲代码的老刘1 天前
MarvellousSuspender浏览器扩展:1.4K星开源标签页冻结神器,Chrome吃内存终结者的干净复活版
前端·chrome
码上上班1 天前
shell 脚本知识点总结
前端·chrome
鬼手点金2 天前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
JAVA老架构AI智能化2 天前
多图叠加比对
前端·javascript·chrome
ShineWinsu2 天前
对于HTML:HTML常见标签的解析—上
前端·面试·html·浏览器·标签·图片·超链接
Zhu7582 天前
开源项目-Sablewisp-轻量、现代的 Chrome 书签管理扩展(Manifest V3)
前端·chrome
Frag0ut4 天前
Chrome数据备份指南:本地备份还原书签密码与扩展配置工具
chrome·google·谷歌浏览器·数据同步·备份工具·配置迁移·书签密码备份