跳到正文
文档导航 · Amazon US Review 页面与翻页接口技术实录
实测知识库

KB-AMAZON-003:Amazon US Review 页面与翻页接口技术实录

平台与场景、验证结论、使用步骤及适用边界。

本页目录
项目内容
平台/站点Amazon 美国站 www.amazon.com
页面Review 页 /portal/customer-reviews/{ASIN}/;商品页 /dp/{ASIN}
接口/portal/customer-reviews/ajax/reviews/get/ref=…(翻页 XHR)
对应 Toolamazon_collect_review_content
对应脚本amazon-review-collector-demo.user.js 0.8.1
字段Review ID、采集/子 ASIN、星级、标题、正文、评论者及主页、日期及原文、国家、变体、已验证购买、Vine、Helpful 数量、Review/图片/视频链接、页面 Review 数量、Global Ratings
整理日期2026-09-15
当前证据等级登录态真实页面结构 + 真机抓包逐字重放 + 合成 HTML fixture 单测;飞书写入见 KB-FEISHU-002

1. 不能越过的证据边界

本文结论全部来自已登录会话的真实页面(作者本机 Chrome,经 CDP 附着)与 Amazon 自己发出的请求。文中只保留 DOM 结构、请求形状、HTTP 状态码、响应字节数和字段名,不保存 Cookie、CSRF token 值或账号信息。

页面结构不是 Amazon 的公开承诺。selector、token 位置和请求头都会随改版变化;任何一条结论过期都必须重新实测,不能用推断替代。

2. URL 与原生筛选参数

Review 页的标准形态:

https://www.amazon.com/portal/customer-reviews/{ASIN}/?_encoding=UTF8&reviewerType=all_reviews&sortBy=recent
参数取值说明
sortByrecent / helpful最新 / 热门
reviewerTypeall_reviews / avp_only_reviews全部 / 仅已验证购买
filterByStarall_stars、five_star … one_star、positive、critical星级
mediaTypeall_contents / media_reviews_only全部 / 仅图片和视频
formatTypecurrent_format仅看当前子体;不需要限定子体时不要带

_encoding=UTF8 无害;ref=cm_cr_arp_… 只是来源追踪,不是必需参数。传入任一子 ASIN,Amazon 会把它落到该 Listing 的 Review 页,因此「输入 ASIN 采整个 Listing」是默认行为。

3. 分页:不是 URL 翻页,必须走 XHR

  • Review 页每页固定 10 条。
  • 纯 GET `&pageNumber=2` 不翻页:实测返回的评论集合与第 1 页完全相同(同一批 Review ID),只是页面外壳重新渲染。想靠改 URL 翻页的思路是错的。
  • 下一页参数在 data-reviews-state-param 属性里(JSON)。同一页面会出现多个,其中若干是 pageNumber: 1 且没有 token 的噪声项;必须取 `pageNumber` 最大且带 `nextPageToken` 的那一个。
  • 真正翻页的请求:
POST https://www.amazon.com/portal/customer-reviews/ajax/reviews/get/ref=cm_cr_getr_d_paging_btm_{page}
Body 字段值备注
sortBy / reviewerType同 URL 参数
filterByStar / mediaType不筛选时传空串
formatType不限定子体时传空串
pageNumber目标页码
nextPageToken上一页给的 token缺了会被拒
shouldAppendtrue
deviceType / canShowIntHeader / reviewsShowndesktop / true / undefined与页面一致即可
reftagcm_cr_getr_d_paging_btm_{page}与 URL 的 ref= 一致
pageSize10
asin目标 ASIN
scopereviewsAjax1
  • 响应体是流式命令序列:多段 JSON 用 \n&&&\n 分隔。每段若形如 [action, selector, html],取索引 2 的 HTML 片段拼接后再解析;非命令行(遥测)应忽略而不是报错。

4. CSRF token:本文最重要的一节

请求头名是 anti-csrftoken-a2z,但值必须取自评论页自己的 token:

<span id="cr-state-object" data-state="{&quot;reviewsCsrfToken&quot;:&quot;…&quot;, …}">
  • 该值是 reviewsCsrfToken 字段内容(实测 64 字符,且已 percent-encode,形如 hKvJbDQ…%2Fdv…)。
  • 页面上还散落着多处同名的 `anti-csrftoken-a2z`:<meta name="anti-csrftoken-a2z">、以及 HTML 转义 JSON 里的 &quot;ajaxHeaders&quot;:{&quot;anti-csrftoken-a2z&quot;:…}。它们和 `reviewsCsrfToken` 不是同一个值。
  • 用错 token 的结果是 HTTP 403 + 响应体 "Page Not Found"(约 2296 字节),看起来像页面不存在,极易误判成「Amazon 改版」或「URL 写错」。

因此脚本里那条曾出现的报错「页面存在下一页但没有 anti-csrftoken-a2z」,真实原因往往是取到了别处的同名 token,而不是 token 消失。

x-amzn-flow-closure-id(取自 <meta name="flow-closure-id">):Amazon 自己的翻页请求会带这个头,但 2026-09-15 实测去掉它仍然返回 200,属于非必需。带上更贴近真实请求,但不能把它当成 403 的原因。

定位这类问题的方法(可复用)

  1. monkey-patch XMLHttpRequest.prototype.open/setRequestHeader/send 与 window.fetch,把 url / headers / body 记进数组;
  2. 点击页面上的 “Show 10 more reviews”,读出 Amazon 自己发出的请求;
  3. 逐字重放该请求(应得 200)——证明请求形状没问题;
  4. 再把自己的请求与它做结构化 diff:逐个头/参数只回答「相同 / 不同 / 缺失」,不回显 token 明文。差异收敛到哪一项,根因就是哪一项。

本次就是靠第 4 步锁定「唯一差异是 token 值」,进而找到 cr-state-object。

5. HTML 解析坑

不要用「非贪婪正则 + backreference」匹配成对标签

/<([a-z][\w:-]*)\b[^>]*>([\s\S]*?)<\/\1\s*>/i   // 危险

([\s\S]*?) 是最短匹配。评论正文里经常有同名的内层标签(最典型是 Amazon 用于高亮的 <span class="a-text-bold">),于是正则在第一个内层 `</span>` 就闭合,正文被截断。实测:I have used this for <span class="a-text-bold">three months</span> and it still works perfectly.<br>Highly recommend. 只解析出前半段。

正确做法是按标签深度计数,找到真正配对的最外层闭合标签,并处理 void 元素(br、img、input…)与不完整片段。

HTML 实体转义的 JSON

Amazon 会把配置 JSON 以实体转义塞进属性(&quot; 代替 ")。直接匹配 "key":"value" 会失败;应先把实体反转义(至少 &quot; / &#34; / &#x22;)再匹配,或把 &quot; 纳入分隔符字符类。

6. 字段来源(data-hook)

字段来源
Review IDdata-hook="review" 节点的 id(部分页面为 data-review-id);跨页与续跑的去重键
星级review-star-rating / cmps-review-star-rating 的文本或 aria-label
标题 / 链接review-title(其文本常带 N out of 5 stars 前缀,需去掉)
日期 / 国家review-date:Reviewed in {国家} on {月} {日}, {年}
变体 / 子 ASINformat-strip 的文本与 href(href 路径里含子 ASIN)
已验证购买 / Vineavp-badge / vine-review-badge
Helpful 数量helpful-vote-statement;one person found this helpful 要当 1,不能用数字解析
正文review-body
图片review-image-tile 的 src / data-src
视频<video>/<source> 的 src、data-video-url,以及 JSON 里的 videoUrl
页面 Review 数量cr-filter-info-review-rating-count,文案可能带 more than(是下限)
Global Ratings页面 N global ratings 文案;与文字 Review 数量不是一回事,不能混用

7. 访问受限与失败诊断

  • 429、登录页、/edgex/guard/、Robot Check / validateCaptcha 一律如实报错并保留已采集结果 + 续跑游标,不绕过验证。
  • 续跑游标不含 Cookie 或 CSRF token;续跑时重新加载首页取新 token,并从保存的 nextPageToken 继续。
  • 报错信息必须带诊断(落地 URL、页面标题、已解析评论数)。只报「页面结构可能已变化」无法定位问题。

8. 已复现结果(2026-09-15,登录会话)

操作结果
GET 首页 /portal/customer-reviews/B09LD2CD1L/200;解析出 11 条卡片;取到 reviewsCsrfToken;取到 pageNumber=2 的 nextPageToken
用页面同款 token + 空 formatType POST 翻页200 / 76420 字节 / 10 段命令 / 含 review 卡片
同上但去掉 x-amzn-flow-closure-id仍 200 → 该头非必需
改用页面别处的 anti-csrftoken-a2z403 + "Page Not Found" → 根因确认
纯 GET &pageNumber=2200,但内容与第 1 页完全相同 → 不翻页

该 ASIN 的页面显示 6611 条评论。实际可采范围同时受 review_limit_per_asin、单轮请求上限和「Amazon 前台只提供最近若干页」约束;0 表示翻到没有下一页为止,不等于能拿到全部历史评论。

9. 数据组织(与脚本约定配套)

  • 本地:一次任务一份报告(数据集 amazon-review-reports,主键 任务编号),全部 Review 明细收在「完整报告」字段。
  • 飞书:明细表,每条 Review 一行(29 列全文本);写入前按「任务编号」查询已有 Review ID,只补写未成功项。
  • 本地单条记录上限 1 MiB:超限要明确报错并保留报告,不截断原文。

10. 未验证范围

  • 非 amazon.com 站点、未登录会话、移动端 UA/布局、Amazon A/B 新评论页。
  • 视频 Review 只记录页面明确披露的 URL,不做解密或绕过站点保护。
  • 本文不含飞书授权、写入与限流细节,见 KB-FEISHU-002。

对改版或未覆盖页面,请提供可公开访问的 ASIN/URL、站点与登录状态、脱敏后的评论区 DOM 或页面诊断,以及人工看到的预期字段。不要提供 Cookie、登录凭据或订单隐私数据。

网页与 Markdown 原文使用同一份内容。开发接口与平台实测资料请从左侧对应分类查阅。