自动化判据取结构不取文案
入档:2026-09-09 来源:给
aigc-topic-cover-factoryskill 写小红书素材采集器(Playwright + 持久化登录态) 验证状态:⭐ 单案三处独立印证(登录墙误判 + 同域资源误收 + URL 参数空操作),三处全是跑真实目标才暴露的,单测无一能发现
一句话
自动化脚本判断「页面处于什么状态」「这条链接是不是我要的东西」时,认结构(DOM 元素、子域、扩展名),不要认文案字符串。文案是产品随时改的展示层,同一个状态往往有好几套说法;结构是前端组件契约,改动频率低一个量级。
更要命的是:文案判据出错时不会报错,而是静默地把垃圾当成果交出来。
三处实测
一、按文案判登录态,漏判成「已登录」
采集器要判断「登录态还在不在」。我写的判据是匹配页面上有没有「扫码登录」四个字。
实测页面写的是「手机号登录」。 结果:
logged_in? : True ← 其实根本没登录
图片直链数 : 30 ← 全是 .js / .css / .ico,一张笔记图都没有
脚本兴高采烈地「成功」了,抓回 30 条前端静态资源。
正解:认结构——未登录时页面会盖一层 .login-container 遮罩,且 section.note-item 笔记卡片数为 0。这两个是组件契约,不随文案改。
def is_logged_in(page):
if page.locator(".login-container").count() > 0:
return False
if page.locator("section.note-item, div.note-item").count() > 0:
return True
return True
二、同域名 ≠ 同类资源
我用正则扫 HTML 找 xhscdn.com 收图片链接。但同一个域名下混着两类完全不同的东西:
| 子域 | 装的是 | 要不要 |
|---|---|---|
fe-static.xhscdn.com | .js / .css / .svg 前端构建产物 | ❌ |
fe-video-qc.xhscdn.com | .ico / .js | ❌ |
sns-webpic-*.xhscdn.com | 笔记正文图 | ✅ |
sns-avatar-*.xhscdn.com | 头像 | ❌ |
正解:两道结构判据叠加——① 读渲染后 img 元素的 currentSrc(而不是正则扫 HTML,扫 HTML 会把内联脚本里的资源链接一并捞进来);② 按子域前缀 + 扩展名白名单过滤。
三、参数「写了」不等于「生效」(2026-09-10 追加)
采集器里有个 upgrade_url(),把直链的 imageView2/2/w/360 重写成 w/1280,我一直以为它在提分辨率。
实测:它是个彻底的空操作。 搜索列表页的直链形如
.../notes_uhdr/<id>!nc_n_webp_mw_1
尺寸由末尾 ! 后的 CDN 预设 决定,imageView2 查询参数被完全忽略——w/1280、w/1920、
把参数全删掉,返回的都是同一张 640×853。而换预设后缀(!nd_dft_wlteh_webp_3 等)一律 403:
路径里带时间 + 哈希令牌,签名和预设是绑死的。
这是本文那条律的第三处印证,而且是最隐蔽的一种:前两处是「判据看错」,这处是 「动作根本没发生,但没有任何东西报错」。参数写上去了、代码跑过了、图也下下来了, 唯一的破绽是分辨率——如果我没去核对返回图的尺寸,这个函数可以永远躺在那儿假装工作。
校验的落点不是「有没有报错」,是**「返回的东西长什么样」**。改了参数就去比对改前改后的产物, 一样就说明参数没生效。
(结论:640 宽对 960×600 输出够用——文字在 1920px 画布上矢量绘制再降采样,锐度不受影响, 背景略软反而贴「真实手机照」的调性。要原图得逐条进笔记详情页取,不划算。)
为什么文案判据必然烂
- 一个状态有多套文案:登录墙可能写「扫码登录」「手机号登录」「验证码登录」,取决于 A/B 分桶和用户历史。你只匹配到其中一种。
- 文案是产品最爱改的东西,改一次不通知任何人;类名改动通常伴随前端重构,频率低得多。
- 文案判据失败的方向是错的:匹配不到 → 判成「没有登录墙」→ 继续跑 → 交出垃圾。它默认「否」,而这里的安全默认应该是「疑罪从有」。
推论一:装完依赖立刻跑一次真实目标
这三处单测全都发现不了——我自己造的假 URL 全部「通过」,因为造数据时脑子里就是那个错误的模型。是装完 Playwright 跑了一次真实搜索页,才把 30 条垃圾链接打到脸上;分辨率那处更晚,是去核对返回图尺寸才露馅。
依赖装完不是终点,是第一次能做真实验证的起点。别装完就宣布完成。
同族参见 用错度量会给出虚假通过_v1。
推论二:留「零结果」告警,别静默成功
结构类名也会变(前端重构就会)。所以判据之外还得有一道兜底:
if not urls:
print("! 一张笔记图都没取到。要么关键词太偏,要么登录态刚失效。", file=sys.stderr)
最危险的不是失败,是拿着垃圾数据宣称成功。 任何「本该有结果却拿到 0 条」的路径,都要吵出来。
如何使用
写任何页面自动化(采集 / 发布 / 巡检)时,先问三句:
- 我判断状态用的是文案还是结构?是文案就换掉。
- 我筛资源用的是域名还是子域 + 类型?同域混装是常态。
- 零结果这条路径,我是吵出来了,还是静悄悄当成功了?
- 我改的那个参数,核对过改前改后的产物有没有变吗?没变就是没生效。
然后:装完依赖,立刻对真实目标跑一次,看回来的东西长什么样,而不是看有没有报错。
关联文档
- 能力边界(哪些活压根不该交给自动化):浏览器插件自动化的能力边界_v1 —— 那篇讲「能不能做」,本文讲「做的时候怎么判」
- 同族心法:用错度量会给出虚假通过_v1 —— 度量选错,全绿也没有意义
- 同族心法:约束型结论先复核律_文档写的不可能会过期_v1 —— 别拿旧结论当当下事实
- 本案出处:代码排版小红书封面工作流_v1(批量封面矩阵一节)· skill 存档 aigc-topic-cover-factory_v1.0_SKILL