单个商品以图搜同款(R3a,先验证签名算法是否有效) #12

Open
opened 2026-09-03 09:30:04 +08:00 by ila · 1 comment
Owner

基本信息

  • 类型:需求 | 所属 Epic:#2 | 所属 MVP:#5 | 阶段:待实施

依赖与并行

  • 前置工单:#9(已完成,负责人真机验证淘宝登录成功)
  • 允许并行:否

为什么拆成 R3a / R3b

签名算法(pcSign 与 MTOP sign)是逆向得来的,是本项目失败风险最高的一环,
而且失败时不会明说签名错误,只返回一个含糊的业务错误码,与「没搜到」
「登录过期」混在一起,排查成本很高。

因此先只做单个商品试搜(R3a),用最小代价回答「算法是否仍然有效」。

  • 算法若已失效:R3a 用约四分之一的工作量即可发现;若直接做批量,
    可能写完队列、并发、断点、随机等待几百行后才发现底层不通,全部返工。
  • 算法若有效:R3a 不浪费,它本身就是批量版的核心调用,R3b 只是在外面
    套一层队列。

另外 R3a 本身可用:负责人可对单个商品手动试搜,判断同款准确度与视频质量,
这个判断只能靠人看,且会影响 R3b 的设计(取前 N 个同款中 N 取多少、
是否需要人工确认,即需求总览里悬置的 Q3)。

风险参考:参考实现 已验证淘宝流程 的文件日期为 2026-08-27,距今约一周,
说明该算法一周前仍然有效。

关于 _m_h5_tk 的窄口子

MTOP 签名必须使用 _m_h5_tk 的值,而 #9 中 CookieNames 刻意只取名称。

AGENTS.md 原文允许此用途:「程序不读取、不复制、不落盘、不上传 Cookie;
只从当前会话读取 _m_h5_tk 用于计算签名,不缓存、不长期复用、不写入日志」。

因此本工单新增 CDP.CookieValue,并在注释中约束:仅用于 MTOP 签名,
用完即弃,不存 SQLite、不写日志、不返回前端、不长期持有。

已在提示词中强调的 Go 特有陷阱

签名是对 JSON 字符串做哈希,键顺序会改变签名结果。Python 的 dict 按
插入顺序序列化,而 Go 的 encoding/json 对 map[string]any 按键名
字母序排序——直接用 map 会产出完全不同的 JSON,签名必错。

要求:必须用 struct(按字段声明顺序输出),禁止用 map;并用
json.Encoder + SetEscapeHTML(false) 对齐 Python 的 ensure_ascii=False。
要求专门写一条测试断言键顺序,防止后人改回 map。

做什么 / 不做什么

  • 做:CookieValue;签名生成;图片下载与缩放;页面内 fetch 调用 MTOP;
    结果解析;表格操作列「搜同款」按钮与结果弹窗。
  • 不做:不写批量、队列、并发、断点、随机等待;不落库。这些属于 R3b。

验收标准

  • 选中一个缺少视频的商品,点「搜同款」能返回淘宝同款列表
  • 结果显示缩略图、标题、价格、店铺、销量,点标题可打开商品页
  • 登录失效时直接报错并提示重新登录,不发起 MTOP 请求
  • 签名相关逻辑有离线单元测试,含键顺序断言
  • 日志中不出现 _m_h5_tk、完整签名原文、图片 base64

验证方式

go vet ./...
go test ./...
cd frontend; npx vite build

真机验证:由负责人在界面上对单个商品试搜。

## 基本信息 - 类型:需求 | 所属 Epic:#2 | 所属 MVP:#5 | 阶段:待实施 ## 依赖与并行 - 前置工单:#9(已完成,负责人真机验证淘宝登录成功) - 允许并行:否 ## 为什么拆成 R3a / R3b 签名算法(pcSign 与 MTOP sign)是逆向得来的,是本项目失败风险最高的一环, 而且**失败时不会明说签名错误**,只返回一个含糊的业务错误码,与「没搜到」 「登录过期」混在一起,排查成本很高。 因此先只做单个商品试搜(R3a),用最小代价回答「算法是否仍然有效」。 - 算法若已失效:R3a 用约四分之一的工作量即可发现;若直接做批量, 可能写完队列、并发、断点、随机等待几百行后才发现底层不通,全部返工。 - 算法若有效:R3a 不浪费,它本身就是批量版的核心调用,R3b 只是在外面 套一层队列。 另外 R3a 本身可用:负责人可对单个商品手动试搜,判断同款准确度与视频质量, 这个判断只能靠人看,且会影响 R3b 的设计(取前 N 个同款中 N 取多少、 是否需要人工确认,即需求总览里悬置的 Q3)。 风险参考:参考实现 `已验证淘宝流程` 的文件日期为 2026-08-27,距今约一周, 说明该算法一周前仍然有效。 ## 关于 `_m_h5_tk` 的窄口子 MTOP 签名必须使用 `_m_h5_tk` 的**值**,而 #9 中 `CookieNames` 刻意只取名称。 AGENTS.md 原文允许此用途:「程序不读取、不复制、不落盘、不上传 Cookie; 只从当前会话读取 `_m_h5_tk` 用于计算签名,不缓存、不长期复用、不写入日志」。 因此本工单新增 `CDP.CookieValue`,并在注释中约束:仅用于 MTOP 签名, 用完即弃,不存 SQLite、不写日志、不返回前端、不长期持有。 ## 已在提示词中强调的 Go 特有陷阱 签名是对 JSON 字符串做哈希,**键顺序会改变签名结果**。Python 的 dict 按 插入顺序序列化,而 Go 的 `encoding/json` 对 `map[string]any` 按键名 **字母序**排序——直接用 map 会产出完全不同的 JSON,签名必错。 要求:必须用 struct(按字段声明顺序输出),禁止用 map;并用 `json.Encoder` + `SetEscapeHTML(false)` 对齐 Python 的 `ensure_ascii=False`。 要求专门写一条测试断言键顺序,防止后人改回 map。 ## 做什么 / 不做什么 - 做:`CookieValue`;签名生成;图片下载与缩放;页面内 fetch 调用 MTOP; 结果解析;表格操作列「搜同款」按钮与结果弹窗。 - 不做:**不写批量、队列、并发、断点、随机等待**;不落库。这些属于 R3b。 ## 验收标准 - [ ] 选中一个缺少视频的商品,点「搜同款」能返回淘宝同款列表 - [ ] 结果显示缩略图、标题、价格、店铺、销量,点标题可打开商品页 - [ ] 登录失效时直接报错并提示重新登录,不发起 MTOP 请求 - [ ] 签名相关逻辑有离线单元测试,含键顺序断言 - [ ] 日志中不出现 `_m_h5_tk`、完整签名原文、图片 base64 ## 验证方式 ```powershell go vet ./... go test ./... cd frontend; npx vite build ``` 真机验证:由负责人在界面上对单个商品试搜。
Author
Owner

真机验证通过

负责人 2026-09-03 在已登录的专属 Chrome 上实测,四项全部通过:

  1. 类型筛选「缺少视频」
  2. 点击操作列「搜同款」
  3. 等待完成
  4. 弹窗显示淘宝同款列表

结论:淘宝的 pcSign 与 MTOP sign 算法目前仍然有效。

这是本项目风险最高的未知项,至此解除。R3a 的拆分目的已达成:
用约四分之一的工作量确认了底层可行,后续批量化只是在此调用外面套队列。

审核阶段的字节级对拍(Claude 执行)

用固定随机值与时间戳,让 Go 实现与参考 Python 实现跑同一组输入:

项 长度 结果
pcSign 44 字节 完全一致
params 1151 字节 完全一致
requestText 1390 字节 完全一致
MTOP sign 32 字节 完全一致
token 提取 — 完全一致

提交

e8db874 feat: 单个商品以图搜同款 (#12)

状态置为待验收。

## 真机验证通过 负责人 2026-09-03 在已登录的专属 Chrome 上实测,四项全部通过: 1. 类型筛选「缺少视频」 2. 点击操作列「搜同款」 3. 等待完成 4. 弹窗显示淘宝同款列表 **结论:淘宝的 pcSign 与 MTOP sign 算法目前仍然有效。** 这是本项目风险最高的未知项,至此解除。R3a 的拆分目的已达成: 用约四分之一的工作量确认了底层可行,后续批量化只是在此调用外面套队列。 ## 审核阶段的字节级对拍(Claude 执行) 用固定随机值与时间戳,让 Go 实现与参考 Python 实现跑同一组输入: | 项 | 长度 | 结果 | |---|---|---| | pcSign | 44 字节 | 完全一致 | | params | 1151 字节 | 完全一致 | | requestText | 1390 字节 | 完全一致 | | MTOP sign | 32 字节 | 完全一致 | | token 提取 | — | 完全一致 | ## 提交 `e8db874` feat: 单个商品以图搜同款 (#12) 状态置为**待验收**。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: chengma/cmsp#12