From 812f8443b71e3424853beeee4d55660637a82300 Mon Sep 17 00:00:00 2001 From: renzhiye Date: Fri, 3 Apr 2026 13:44:53 +0800 Subject: [PATCH] =?UTF-8?q?docs(research):=20=E8=A1=A5=E5=85=85=E5=A4=A9?= =?UTF-8?q?=E7=8C=AB=E8=AF=A6=E6=83=85=E4=B8=8E=E8=AF=84=E8=AE=BA=E6=8A=93?= =?UTF-8?q?=E5=8F=96=E7=A0=94=E7=A9=B6=E7=BB=93=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/TmallCrawlerResearch.md | 179 +++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 docs/TmallCrawlerResearch.md diff --git a/docs/TmallCrawlerResearch.md b/docs/TmallCrawlerResearch.md new file mode 100644 index 0000000..5d955f9 --- /dev/null +++ b/docs/TmallCrawlerResearch.md @@ -0,0 +1,179 @@ +# 天猫详情页与评论抓取研究 + +- 状态:Draft +- 更新时间:2026-04-03 +- 关联任务:`S3-01` + +## 结论 + +1. 天猫详情和评论链路已经可以明确到具体入口与 API,不再是“靠 DOM 碰运气”的问题。 +2. 默认可交付路径应是“登录态页面状态解析 + 登录态模板回放”的组合,不是匿名直连。 +3. 2026-04-03 的实测里,天猫详情和评论 API 在服务端匿名请求下都会回到带登录跳转的 `RGV587_ERROR`,因此当前必须把登录态作为前置依赖。 +4. 详情页存在可稳定访问的 PC SSR 壳路由,适合做资源发现、版本跟踪和模板漂移观测;真正稳定可回放的详情数据来源则应优先落在登录态 HTML/SSR 内嵌状态,而不是继续依赖易漂移的详情 mtop。 +5. 最新一轮已把天猫 `search` 主路径补到服务端:直接回放 `https://s.taobao.com/search?q=&tab=mall` 的登录态 HTML,并优先解析内嵌 `g_page_config` / JSON 负载,必要时再从商品链接块回退提取候选。 + +## 已验证入口 + +### 1. 商品详情壳页 + +- 直接访问 `https://detail.tmall.com/item.htm?id=`,当前会返回登录跳转页,并带 `x-sec-reason: FAIL_SYS_SESSION_EXPIRED`。 +- 直接访问 `https://detail.tmall.com/wow/z/app/tbpc/pc-detail-ssr-2025/home?itemId=`,可稳定拿到 SSR 壳页与资源清单。 +- 2026-04-03 实测的资源版本为: + - `https://g.alicdn.com/code/npm/@ali/tbpc-pc-detail-ssr-2025/0.0.54/js/data-loader.js` + - `https://g.alicdn.com/code/npm/@ali/tbpc-pc-detail-ssr-2025/0.0.54/js/p_home.js` + +### 2. 详情 API + +`data-loader.js` 暴露了两条详情接口: + +- `mtop.taobao.pcdetail.data.get` +- `mtop.taobao.pcdetail.business.data.get` + +当前主链更像是: + +1. 详情页 SSR 壳加载 `data-loader.js` +2. `data-loader.js` 组装 `data` 负载: + - `id` + - `detail_v: "3.3.2"` + - `exParams.queryParams` + - `exParams.domain` + - `exParams.path_name` + - `exParams.pcSource` + - `exParams.logicVer` + - `exParams.nonce` +3. 浏览器中的 `lib-mtop` 发起详情请求 + +### 3. 评论 API + +`p_home.js` 暴露了两条评论接口: + +- PC 评论:`mtop.alibaba.review.list.for.new.pc.detail` +- H5 评论兜底:`mtop.taobao.rate.detaillist.get` + +实测与 bundle 还原出的关键参数如下。 + +PC 评论请求: + +- `itemId` +- `bizCode` + - 天猫为 `ali.china.tmall` + - 淘宝为 `ali.china.taobao` +- `channel: "pc_detail"` +- `pageSize` +- `pageNum` +- 可选 `rateType` +- 可选 `orderType` + +H5 评论请求: + +- `auctionNumId` +- `pageNo` +- `pageSize` +- `showTrueCount: false` +- `rateSrc: "pc_rate_list"` +- 可选 `rateType` +- 可选 `orderType` +- 可选 `expression` + +### 4. 2026-04-03 追加实机结论 + +- 当前真实商品页 `https://detail.tmall.com/item.htm?id=934454505228...` 的页面内详情请求稳定命中: + - `mtop.tmall.kangaroo.core.service.route.aldlampservicefixedresv2` +- 该接口在已登录浏览器中的真实返回里,`data.resultValue["36500751"].data` 只暴露 `distinctId`、`dataSetId`、`resId` 等路由信息,本身不是最终商品详情快照。 +- 同一页面的 SSR 内嵌脚本 `window.__ICE_APP_CONTEXT__` 已直接包含: + - 标题 + - 店铺名 / 店铺链接 / 店铺类型 + - 主图 + - 当前展示价格 / 划线价 + - 已售文案 + - 评论总量与首屏评论摘要 +- 结论: + - 商品详情抓取应优先采用“登录态 HTML + `window.__ICE_APP_CONTEXT__` 解析”。 + - 评论抓取继续采用 `mtop.taobao.rate.detaillist.get` 更合适。 + - 服务端回放评论模板时,必须基于 Cookie 中 `_m_h5_tk` 重新计算 `t/sign`;仅替换 `data` 而不重签名会被 mtop 拒绝。 + +## 2026-04-03 实测结果 + +### 0. MCP 浏览器实时登录态闭环 + +- 使用 MCP Playwright 浏览器直接打开真实商品页 `https://detail.tmall.com/item.htm?id=934454505228`,页面可在登录态下稳定打开。 +- 通过 `page.context().cookies()` 抽取当前 `*.tmall.com` 与 `detail.tmall.com` Cookie,回灌到 `POST /api/platforms/tmall/live-session` 后,`GET /api/platforms/tmall/live-product-preview?itemId=934454505228&commentCount=20&page=1&maxPages=2` 已实机返回 200。 +- 实机返回中已包含: + - 商品详情:标题、店铺、主图、价格、评论总量。 + - 评论结果:标签、分页信息,以及 20 条真实评论样本。 +- 本轮还暴露并修复了一个真实问题:`mtop.taobao.rate.detaillist.get` 返回的是 JSONP,服务端解析器此前未先解包 `mtopjsonp(...)`,导致“请求成功但评论为空”。该问题已在 `apps/api` 修复并补齐回归测试。 + +### 1. 详情 API + +匿名服务端请求 `mtop.taobao.pcdetail.data.get` 时,返回: + +- `ret: ["RGV587_ERROR::SM::..."]` +- `data.url` 指向 `https://login.taobao.com/member/login.jhtml?...` + +结论: + +- 详情 API 当前必须依赖登录态 Cookie。 +- 仅靠匿名 `_m_h5_tk` / H5 签名不足以形成稳定交付链路。 + +### 2. 评论 API + +匿名服务端请求: + +- `mtop.alibaba.review.list.for.new.pc.detail` +- `mtop.taobao.rate.detaillist.get` + +同样返回: + +- `ret: ["RGV587_ERROR::SM::..."]` +- `data.url` / `data.h5url` 指向淘宝登录页 + +结论: + +- 评论接口虽然前端代码里标记为 `needLogin: false`,但当前实测依然被服务端登录门槛或风控前置拦住。 +- 对项目来说,评论抓取和详情抓取一样,都要走“先登录、后回放”。 + +## 已落库的工程推进 + +本轮已在 `apps/api` 补了天猫 live-session 与任务主链骨架: + +- `apps/api/src/platforms/tmall/live-session.ts` +- `apps/api/src/platforms/tmall/parsers.ts` +- `apps/api/src/platforms/tmall/types.ts` +- `apps/api/src/platforms/tmall/utils.ts` + +当前能力包括: + +1. 导入天猫 `cookieHeader` +2. 导入评论模板 URL,并保留详情模板 URL 作为漂移观测输入 +3. 登录态搜索页改为 `s.taobao.com/search?...&tab=mall` HTML 拉取,并解析内嵌状态与候选链接 +4. 商品详情改为登录态详情页 HTML 拉取,并解析 `window.__ICE_APP_CONTEXT__` 的 SSR 内嵌状态 +5. 评论模板按新 `itemId`、页码、每页数量改写请求参数 +6. 评论回放前基于 `_m_h5_tk` 按真实 mtop 公式重算 `t/sign` +7. 评论多页回放后做去重聚合 +8. 对登录跳转响应统一抛出 `409`,可直接接入 `NeedLogin` / `Blocked` +9. 暴露 `live-search-preview` / `live-detail-preview` / `live-reviews-preview` / `live-product-preview` 预览入口 +10. 把天猫实时 `search/detail/reviews` 接入任务执行主链,并新增 JD + 天猫双平台 live 主回归、`Blocked -> retry success` 报告升版回归、`Blocked -> retry blocked -> report unchanged` 稳定性回归,以及 `SearchBlocked` 恢复后二次确认只补跑新恢复平台的回归 + +## 下一步建议 + +1. 用真实登录态继续固化搜索页、评论模板与样本响应,验证 `apps/api` 的 preview 接口: + - `GET /api/platforms/tmall/live-search-preview` + - `POST /api/platforms/tmall/live-session` + - `GET /api/platforms/tmall/live-detail-preview` + - `GET /api/platforms/tmall/live-reviews-preview` + - `GET /api/platforms/tmall/live-product-preview` +2. 抓一轮真实任务闭环: + - 导入 live session + - 创建任务并选中带 `itemId` 的天猫候选 + - 验证报告证据是否落到真实 `search/detail/reviews` 回放 +3. 固化第一批真实 fixture / HAR,补齐 `S0-02` +4. 继续扩大双平台主回归包覆盖面;`SearchBlocked` / `NoResult` / `Blocked` 组合、`Blocked -> retry success` 升版、`Blocked -> retry blocked -> report unchanged`,以及 `SearchBlocked` 恢复后二次确认不重复执行已完成平台已覆盖,后续补更多失败/恢复组合与真实 fixture 驱动回归 +5. 如果模板漂移频繁,再补 `L2` 模板刷新与 `L3` 登录恢复 + +## 参考链接 + +- +- +- +- +-