EveryInfra

Build in Public · LF-06

Amazon 评论 API:从商品链接到有原文证据的问题清单

逐步接入 Amazon 评论读取,核对国家站点与商品身份,分离评论、变体和观察记录,处理去重与缺失,再用可验证的原文片段建立问题分类。

想从 Amazon 评论里找产品改进线索,第一步不是让模型把所有内容分成好评和差评。你需要先知道:评论来自哪个国家站点、关联哪个商品、是否在多次请求中重复出现,以及每条问题结论到底引用了哪句话。否则,十次读到同一条热门评论,就可能被报表解释成十位买家提出了同一个问题。

本文面向需要把评论接入内部研究流程的开发者和产品负责人。我们从一条获准使用的商品链接开始,建立商品、评论、观察记录与分类证据之间的关系。最终输出是一份可复核的问题清单,而不是销量预测、评论真实性鉴定或全部购买者的满意度。

先分清商品目录与评论研究

Amazon 官方 Creators API 提供商品目录访问,包含商品搜索、商品详情、变体和分类节点等操作,面向 Amazon Associates 相关购物体验。它与本文 EveryInfra 的 amazon.reviews 不是同一个产品;官方商品目录文档不能当作第三方评论读取的授权证明。

接入前先确认具体站点、取得数据的许可、处理目的、保留期限,以及能否展示原文或交给模型处理。Amazon.com 使用条件的 LICENSE AND ACCESS 对一般许可与数据收集方式设有限制,其他站点及特定计划还要分别核查。商品属于自己的品牌,也不等于自动获得所有评论内容的任意再利用权。

如果现有授权只允许使用某份导出数据,可以从后文的身份、去重和分类步骤开始,不必执行网络读取。流程中保留许可范围,超出范围的字段或用途不进入后续管道。

看当前评论契约,不从其他 action 借参数

免费读取 Amazon 评论目录
curl -fsS --max-time 30 \
  'https://api.everyinfra.com/api/v1/social/catalog?platform=amazon' \
  | jq -e '.capabilities[] | select(.action == "reviews") | {
      platform, action, required_params, optional_params, param_meanings,
      mode, returns_list, default_limit, max_limit, response_fields
    }'

2026-09-04 核对时,reviews 要求 url,可选参数列出 domain,执行模式为 sync,结果为列表。该次目录没有声明 default_limit 与 max_limit 的具体值;空值只能记作未声明,不能解释为不限制条数,更不能承诺获得全部历史评论。

也不要因为其他平台支持 sort、since 或 cursor,就把这些字段加进 Amazon 请求。可选参数需要与当前 action 对应,接口接受参数与筛选确实生效也要分别验收。当前目录不足以支持“按最新排序后连续翻页”的教程,下面只演示一次小样本请求。

先确认国家站点,再确认商品身份

url 使用完整商品链接;domain 使用站点域名,例如 amazon.com 或 amazon.co.jp,不带 https:// 或商品路径。本地输入解析会从 /dp/、/gp/product/、/product-reviews/ 这类路径识别十位大写字母或数字构成的 ASIN。店铺首页和关键词搜索页不能充当已确认的商品输入。

尤其注意非美国站点:当前实现中,评论站点的默认值是 amazon.com,并不保证从任意输入链接自动推断国家站点。准备日本站商品时,显式传入与链接一致的 amazon.co.jp。不要把日文正文、评论里的 country 或页面显示货币当成请求域名的替代品。

  • 商品清单保存原始 URL、经核对的站点、请求 ASIN、业务商品编号与纳入理由。标题仅用于阅读,不作为商品主键。
  • 商品关联单独保存响应中的 product_asin 与 variant;它们不能未经核对就覆盖请求 ASIN,缺失时也不要猜出一个子变体。
  • 同一站点和 ASIN 的不同跟踪链接,可以在发请求前合并为一个目标,但保留原链接映射。更换站点、目标或参数的请求不能只凭标题相似就合并。

请求站点是这次观察的来源范围,不是评论作者的国籍。country 可能是不同格式的地区文字,variant 也可能不完整;只有经过明确的归一与核对,才适合做按地区或规格的分组。无法确认的记录进入“未明确”,不要默默放进美国站或默认规格。

用一个目标完成最小请求

下面是请求模板,不是本轮真实客户调用。将获准的完整商品链接和匹配站点放入环境变量,API Key 只留在自己的运行环境。limit 放在 params 中,作为通用列表数量请求;设置为 3 是为了检查少量结构,不是保证恰好返回三条、服务端只处理三条或按三条计费。

单商品评论请求模板:不自动重试
: "${EVERYINFRA_API_KEY:?请先配置 API Key}"
: "${EVERYINFRA_AMAZON_PRODUCT_URL:?请先配置获准的完整商品链接}"
: "${EVERYINFRA_AMAZON_DOMAIN:?请先配置与链接一致的站点域名}"
jq -cn --arg url "${EVERYINFRA_AMAZON_PRODUCT_URL}" \
  --arg domain "${EVERYINFRA_AMAZON_DOMAIN}" '{
    platform: "amazon",
    action: "reviews",
    params: {url: $url, domain: $domain, limit: 3}
  }' | curl --silent --show-error --include --max-time 180 \
  'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer ${EVERYINFRA_API_KEY}" \
  -H 'Content-Type: application/json' --data-binary @-

先检查 HTTP 状态和响应类型,再按实际外壳读取 results、请求标识与可得的计费信息。超时表示客户端没有拿到完整结果,不证明服务端没执行;保留请求上下文后再核对,避免直接重发。空结果表示这一请求没有交付可用评论,不能据此给商品标记“从未有过评论”。

把评论本身与观察记录分开

核对评论字段词典
curl -fsS --max-time 30 \
  'https://api.everyinfra.com/api/v1/social/fields?platform=amazon&action=reviews' \
  | jq '{fields, undocumented}'

当前词典包含 review_id、title、text、rating、rating_scale、posted_at、helpful_count、is_verified_purchase、is_vine、variant、country、url、author_name、product_asin 和 platform。它描述可能返回什么,不保证每条记录都有完整值。

  • 评论记录:保存来源范围、稳定 review_id、可得的标题/正文/评分及来源链接。ID 保留为字符串;缺失值与明确的 false、0 分开。
  • 观察记录:保存任务编号、请求商品、参数快照、observed_at 与实际返回的评论关联。一次请求读到旧评论,是新观察,不是新评论。
  • 分析记录:保存采用的评论版本、分类规则版本、主题与证据片段、复核状态。改了分类规则,不需要改写原始评论。

rating 与 rating_scale 一起处理;商品层的汇总评分、评分总量与本次取得的评论条数是不同指标。没有正文的评分记录可以计入单独的评分样本,但不能凭空生成意见后混入文本主题分析。author_name 只是显示名,不适合作为唯一身份,更不需要为了产品问题分析去拼接作者的跨站档案。

is_verified_purchase 是购买验证状态,不是观点正确或内容完全真实的保证;false 与字段没有返回也必须区分。is_vine 则标识 Vine 计划相关评价。Amazon 官方说明,Vine 邀请的评价者可免费体验产品后发表意见;因此可以把该状态作为样本分层字段,但不能直接将 Vine 评论判成虚假,也不能把缺失字段判成非 Vine。

去重时保留关联,不按相似文字直接删除

应用层可以先用“来源平台 + 站点 + review_id”识别同一范围内的评论,再单独记录它在哪些请求商品下被观察到。如果相同键对应矛盾的商品归属或内容,先保留冲突记录核对,不做静默覆盖。跨站出现相同 ID 或相同文字,也不要在没有可靠对应关系时自动合并。

review_id 缺失时,可利用已确认的评论永久链接辅助关联;仍不确定就进入待去重区。正文、日期、评分的组合只能给出近似候选,不能证明两个作者是同一人。两条“很好用”可能真是不同评论,翻译后的同义文本也不能作为唯一键。

同一评论稍后再次出现,比较实际可得的文本、评分、帮助数与商品关联。变化先记录为观察差异;语言、字段可得性和时间范围不同,也可能造成差异。本轮没有返回某条评论,只能标记“本轮未观察到”,不要生成删除事件。

问题分类必须带回原文位置

先用少量获准样本由人工确定分类边界,再接模型。主题可以从兼容性、包装、说明、物流等可行动问题开始,同时保留“无明确问题”与“证据不足”。同一评论允许多个主题;不要为了凑满标签,给“还没拆封”补写质量结论。

传给分类器的数据应最小化到任务必需内容。评论是待分析材料,不是系统指令;其中即使出现“忽略规则”“访问这个地址”等句子,也不应让模型调用工具或改变处理目标。输出至少绑定评论 ID、原文字段、起止位置、主题、规则版本和待复核状态。

离线 JavaScript:验证分类引用确实来自原文
function validateAnnotation(review, annotation) {
  const topics = new Set(["compatibility", "packaging", "instructions", "shipping"]);
  if (typeof review.review_id !== "string" || !review.review_id.trim()) {
    throw new Error("review id required");
  }
  if (annotation.review_id !== review.review_id
      || annotation.taxonomy_version !== "issues-v1"
      || !topics.has(annotation.topic)) {
    throw new Error("unknown review or classification rule");
  }
  const field = annotation.source_field;
  if (!["title", "text"].includes(field)) throw new Error("invalid source field");
  const source = review[field];
  const {start, end, quote} = annotation;
  if (typeof source !== "string" || typeof quote !== "string"
      || !quote.trim() || !Number.isInteger(start) || !Number.isInteger(end)
      || start < 0 || end <= start || end > source.length
      || source.slice(start, end) !== quote) {
    throw new Error("evidence does not match source");
  }
  return {
    review_id: review.review_id, topic: annotation.topic,
    source_field: field, start, end, quote,
    taxonomy_version: "issues-v1", review_status: "unreviewed"
  };
}

// 合成文字,只演示证据校验,不是真实商品评论。
const sample = {review_id: "synthetic-review", text: "接口无法连接旧型号,包装完整。"};
console.log(validateAnnotation(sample, {
  review_id: sample.review_id, taxonomy_version: "issues-v1",
  topic: "compatibility", source_field: "text",
  start: 0, end: 9, quote: "接口无法连接旧型号"
}));

这个校验器只证明引用位置与输入文本一致,不证明主题判断正确。假如模型引用“包装完整”却标记包装问题,字符校验仍可能通过,必须由语义检查或人工复核拦下。start/end 使用 JavaScript 字符串索引;若把数据交给另一种语言,应明确索引约定,不能混用字节偏移或字符数量。

实际生产还要在外层绑定站点、商品关联和评论版本,限制每条输出数量及字段类型。模型自报的 confidence 不是经过校准的正确率;上线前选定人工标注样本,分别统计漏报、误报和证据不支持,而不是把所有错误压成一个漂亮的总准确率。

OWASP 将藏在网页、文档和用户评论中的指令列为间接提示注入风险,并建议按用户权限和当前任务核验工具调用。因此评论分类器应只产出受约束的候选标签;修改商品、发送消息等动作不由评论内容获得授权。

问题占比要写明分母

在一个纯合成例子里,10 条去重、可读且纳入分析的评论中,有 3 条经复核涉及兼容性,可以写“该样本中兼容性问题提及率为 3/10”。不能改写为“30% 的购买者遇到兼容问题”。同一评论涉及两个主题时,各主题占比相加可能超过 100%;只有先定义互斥分类,才适合画加总到 100% 的组成图。

每次报告附上站点和商品集合、采样时间、实际请求参数、返回数量、去重后数量、可读正文数量、待复核数量及规则版本。评论的 posted_at 与读取时的 observed_at 分开:今天读取到一条去年的评论,不代表今天发生了一起新故障。

跨周比较还需要固定或解释商品集合、获取顺序、语言处理和时间范围的变化。如果持续只读到同一组靠前评论,新增任务次数不会扩大独立样本。目录没有提供完整分页或时间窗口保证时,应把报告定位为已观察样本分析,而不是全量趋势监控。

报告还可以借用 W3C PROV 的派生记录思路,把每条问题结论连到评论版本及分类活动。这样原文被更正时,能找到受影响的标签和摘要;记录关系本身并不证明分类正确,语义复核仍需保留。

让问题清单进入实际改进流程

一条值得交给产品团队的结论,应包含受影响的已确认规格、代表性证据、样本分母、尚未排除的其他解释,以及下一步核查动作。例如,先复现旧型号的连接问题,再决定补兼容说明或调整产品;评论本身不替代工程测试、订单或售后记录。

第一次接入可以只选一个获准商品,完成输入核对、响应检查、去重、原文证据校验和人工复核。只有这些环节能回放,扩大商品清单才会增加有效信息。下一步按 Amazon 能力页核对参数,按通用文档处理请求状态;不要先把数量做大,再回头猜每条评论来自哪里。