从零开发 ReviewIQ:一款接入 AI 的亚马逊评论情报分析 Chrome 扩展(完整实战)
从零开发 ReviewIQ:一款接入 AI 的亚马逊评论情报分析 Chrome 扩展(完整实战)
本文记录了我从零开发一款面向亚马逊卖家的 Chrome 扩展全过程——它能自动抓取商品评论,结合 GPT-4o / Claude 生成竞品弱点分析、产品健康评分和用户画像洞察报告,直接嵌入亚马逊页面展示。

一、为什么要做这个工具?
做亚马逊的卖家朋友都知道,评论是利润的风向标:
- 竞品差评多 = 你的选品机会
- 自己差评多 = 退货率飙升的预警
- 用户反复提到某个需求 = 下一款爆品的灵感
但手动翻几百条评论太低效了。市面上的工具(Helium 10、Jungle Scout)要么贵、要么不够智能。
所以我做了 ReviewIQ —— 一个直接嵌入亚马逊页面的 AI 情报面板。
二、产品定位:不是工具,是决策情报
三大核心视图:
| 视图 | 功能 | 价值 |
|---|---|---|
| 🎯 竞品弱点透视 | 差评词云、1-3星归类、AI弱点排序、竞争策略建议 | 精准选品 |
| 🩺 产品体检报告 | AI健康评分(0-100)、风险识别、退货原因、紧急度排序 | 预防亏损 |
| 👥 用户画像洞察 | AI用户画像、未满足需求、市场机会、痛点句挖掘 | 发现蓝海 |
核心理念:这不是工具,而是一份直指利润的决策情报。
三、技术架构总览
┌─────────────────────────────────────────────────────┐
│ Chrome Extension (MV3) │
├──────────┬───────────┬──────────┬───────────────────┤
│content.js│ panel.js │ popup.js │ options.js │
│ DOM抓取 │ 页内面板 │ 快捷入口 │ API Key配置 │
├──────────┴───────────┴──────────┴───────────────────┤
│ background.js (Service Worker) │
│ 消息中转 · AI API 调用 · 数据缓存 │
├─────────────────────────────────────────────────────┤
│ OpenAI API / Anthropic Claude API │
└─────────────────────────────────────────────────────┘
技术选型:
- Chrome Extension Manifest V3(最新标准,2024+ 必须)
- 纯 Vanilla JS(无框架依赖,加载快、包体小、审核易通过)
- Service Worker 做 API 代理(解决 content script CORS 限制)
- chrome.storage.sync 持久化用户配置(跨设备同步)
- CSS 命名空间隔离(
#amz-iq-前缀,不污染亚马逊页面)
四、项目结构
chrome/
├── manifest.json # MV3 扩展配置(权限、content_scripts、host_permissions)
├── background.js # Service Worker:消息中转 + AI API 调用
├── content.js # 注入亚马逊页面:DOM 评论抓取 + 解析
├── panel.js # 页内情报面板:三大分析视图 + AI 报告渲染
├── panel.css # 面板样式(z-index 顶层 + 命名空间隔离)
├── popup.html # 扩展弹窗 UI(快捷入口)
├── popup.js # 弹窗逻辑(注入 + 打开面板)
├── options.html # 设置页 UI(API Key 配置)
├── options.js # 设置页逻辑
└── icons/ # 扩展图标(16/48/128px)
├── icon16.png
├── icon48.png
└── icon128.png
五、核心实现拆解
5.1 Manifest V3 配置
{
"manifest_version": 3,
"name": "ReviewIQ · Amazon Seller Insights",
"version": "1.0.0",
"permissions": ["activeTab", "scripting", "storage", "tabs"],
"host_permissions": [
"*://*.amazon.com/*",
"*://*.amazon.co.uk/*",
"*://*.amazon.de/*",
"*://*.amazon.co.jp/*",
"https://api.openai.com/*",
"https://api.anthropic.com/*"
],
"options_page": "options.html",
"background": { "service_worker": "background.js" },
"content_scripts": [{
"matches": ["*://*.amazon.com/*", "*://*.amazon.co.uk/*"],
"js": ["content.js", "panel.js"],
"css": ["panel.css"],
"run_at": "document_idle"
}]
}
关键点:
host_permissions要覆盖所有亚马逊站点 + AI API 域名content_scripts里同时注入抓取逻辑和面板 UIoptions_page注册设置页让用户填 API Key
5.2 评论抓取:兼容新旧版亚马逊 DOM
亚马逊页面结构经常变动,我的解决方案是广谱选择器 + 属性模糊匹配 + 最长文本兜底三层保障:
// 第一层:广谱容器选择器
const REVIEW_SELECTORS = [
'[data-hook="review"]',
'[data-hook="cmps-review"]',
'li[id^="customer_review"]',
'div[id^="customer_review"]',
'[data-cel-widget^="customer_review"]'
].join(', ');
const nodes = document.querySelectorAll(REVIEW_SELECTORS);
// 第二层:字段提取用属性后缀/子串匹配
let bodyEl =
el.querySelector('[data-hook="review-body"] span') ||
el.querySelector('[data-hook$="body"]') ||
el.querySelector('[data-hook$="body-content"]') ||
el.querySelector('[data-hook*="review-text"]') ||
el.querySelector('.review-text-content');
// 第三层:终极兜底 —— 取容器内最长的叶子文本
if (!body) {
const candidates = el.querySelectorAll('span, p, div');
let longest = '';
candidates.forEach((c) => {
// 只取叶子节点(不包含子元素的节点)
if (c.querySelector('span,p,div')) return;
const t = c.textContent.trim();
if (t.length > longest.length) longest = t;
});
if (longest.length > 16) body = longest;
}
为什么要这样设计? 因为亚马逊 2024-2025 年把 data-hook="review-body" 改成了其他名字,如果你只写死选择器,随时可能抓到 0 条。
5.3 多页抓取 + 反爬检测
async function scrapeAllReviews({ asin, maxPages, sortBy, onProgress }) {
// Step 0:先扫当前 DOM(不需要 fetch,立即可用)
const domReviews = scrapeReviewsFromRoot(document);
onProgress({ source: 'dom', pageCount: domReviews.length });
// Step 1:fetch 多页 /product-reviews/<ASIN>
for (let page = 1; page <= maxPages; page++) {
const url = `https://www.amazon.com/product-reviews/${asin}` +
`?pageNumber=${page}&sortBy=${sortBy}`;
const resp = await fetch(url);
const html = await resp.text();
const doc = new DOMParser().parseFromString(html, 'text/html');
// 反爬检测
if (isBlockedPage(doc)) {
result.blocked = true;
break;
}
const pageReviews = scrapeReviewsFromRoot(doc);
allReviews.push(...pageReviews);
onProgress({ page, pageCount: pageReviews.length, total: allReviews.length });
}
}
// 登录墙 / 验证码检测
function isBlockedPage(doc) {
return !!(
doc.querySelector('#captchacharacters') ||
doc.querySelector('form[action*="signin"]') ||
doc.title?.includes('Robot Check')
);
}
5.4 页内面板注入
不用传统 popup 弹窗,而是直接注入到亚马逊页面里,卖家不需要切换窗口:
// 右下角悬浮按钮(FAB)
const fab = document.createElement('div');
fab.id = 'amz-iq-fab';
fab.textContent = 'IQ';
document.documentElement.appendChild(fab);
// 右侧抽屉式面板
const panel = document.createElement('div');
panel.id = 'amz-iq-panel';
document.documentElement.appendChild(panel);
// 点击打开/关闭
fab.addEventListener('click', () => panel.classList.add('open'));
CSS 关键样式:
#amz-iq-fab {
position: fixed;
right: 22px; bottom: 24px;
width: 56px; height: 56px;
z-index: 2147483646; /* 顶层,不被遮挡 */
background: #f97316;
border-radius: 50%;
cursor: pointer;
}
#amz-iq-panel {
position: fixed;
top: 0; right: 0;
width: 460px; height: 100vh;
z-index: 2147483647;
transform: translateX(100%); /* 默认隐藏 */
transition: transform .3s ease;
}
#amz-iq-panel.open {
transform: translateX(0); /* 滑入 */
}
5.5 AI 分析:GPT-4o / Claude 双引擎
核心设计:在 Service Worker 中调用 API,避免 content script 的 CORS 限制。
评论压缩(控制 token 用量):
function compressReviews(reviews, maxChars = 12000) {
// 优先保留差评(分析价值最高),好评只取少量对比
const neg = reviews.filter(r => r.rating <= 3);
const pos = reviews.filter(r => r.rating >= 4).slice(0, 5);
const selected = [...neg, ...pos];
let result = '';
for (const r of selected) {
const line = `[${r.rating}★] ${(r.title || '').slice(0, 60)} | ${(r.body || '').slice(0, 200)}\n`;
if (result.length + line.length > maxChars) break;
result += line;
}
return result;
}
结构化 Prompt(让 AI 直接输出可解析的 JSON):
function buildPrompt(meta, reviewsText) {
return `你是一位亚马逊电商数据分析专家。以下是商品 "${meta.productTitle}" (ASIN: ${meta.asin}) 的用户评论摘录。
评论数据:
${reviewsText}
请输出严格 JSON 格式的分析报告:
{
"competitor": {
"weaknesses": [{"point": "具体弱点", "severity": "high/medium/low", "evidence": "评论原文片段", "count": 出现次数}],
"exploitStrategy": "竞品如何利用这些弱点的策略建议"
},
"health": {
"score": 0-100整数,
"risks": [{"issue": "风险描述", "urgency": "critical/high/medium/low", "action": "建议行动"}],
"returnReasons": ["退货原因1", "退货原因2"],
"summary": "产品健康总结"
},
"insight": {
"personas": [{"label": "用户群标签", "description": "特征描述", "needs": "核心诉求"}],
"unmetNeeds": ["需求1", "需求2"],
"opportunities": ["市场机会1", "市场机会2"],
"summary": "用户洞察总结"
}
}
要求:所有文本使用中文,仅输出 JSON。`;
}
双 API 支持:
// OpenAI
async function callOpenAI(cfg, prompt) {
const resp = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${cfg.apiKey}`
},
body: JSON.stringify({
model: cfg.model || 'gpt-4o-mini',
messages: [{ role: 'user', content: prompt }],
max_tokens: 2000,
temperature: 0.4
})
});
const data = await resp.json();
return data.choices?.[0]?.message?.content || '';
}
// Claude
async function callClaude(cfg, prompt) {
const resp = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': cfg.apiKey,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: cfg.model || 'claude-sonnet-4-20250514',
max_tokens: 2000,
messages: [{ role: 'user', content: prompt }]
})
});
const data = await resp.json();
return data.content?.[0]?.text || '';
}
5.6 本地统计分析(无需 AI 也能用)
即使不配置 API Key,面板也能给出基础分析:
// 差评关键词词频
function wordFreq(reviews, { ratingMax = 3 }) {
const map = new Map();
reviews.forEach((r) => {
if (r.rating > ratingMax) return;
tokenize(`${r.title} ${r.body}`).forEach((w) =>
map.set(w, (map.get(w) || 0) + 1)
);
});
return [...map.entries()].sort((a, b) => b[1] - a[1]);
}
// 紧急度评分 = (5 - 评分) × (1 + 有用数) × 时间衰减
function urgencyScore(r) {
const days = (Date.now() - parseDateMs(r.date)) / 86400000;
const decay = days < 7 ? 1.5 : days < 30 ? 1 : days < 90 ? 0.6 : 0.3;
const sev = Math.max(0, 5 - (r.rating || 5));
return sev * (1 + (r.helpful || 0)) * decay;
}
// 痛点句提取:从差评里找包含转折/否定关键词的句子
const PAIN_HINTS = /\b(but|however|wish|disappointed|broke|doesn't|can't|return|waste|poor)\b/i;
function painSentences(reviews, limit = 8) {
const out = [];
for (const r of reviews) {
if (r.rating > 3 || !r.body) continue;
const sents = r.body.split(/(?<=[.!?])\s+/);
for (const s of sents) {
if (s.length > 14 && PAIN_HINTS.test(s)) {
out.push({ s, rating: r.rating, helpful: r.helpful || 0 });
}
}
}
return out.sort((a, b) => b.helpful - a.helpful).slice(0, limit);
}
5.7 消息通信机制
Chrome Extension 各模块通过消息传递协作:
// panel.js → background.js(请求 AI 分析)
const resp = await chrome.runtime.sendMessage({
type: 'AI_ANALYZE',
payload: { meta, reviews }
});
// background.js 监听并处理
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === 'AI_ANALYZE') {
runAiAnalysis(msg.payload.meta, msg.payload.reviews)
.then(report => sendResponse({ ok: true, data: report }))
.catch(e => sendResponse({ ok: false, error: e.message }));
return true; // 保持异步通道
}
});
六、AI 报告渲染效果
抓取完成后,面板会显示 loading 动画,5-15 秒后 AI 报告出现在各 Tab 顶部:
竞品弱点 Tab:
- 🤖 AI 竞品弱点深度分析(按严重程度排序的弱点卡片)
- 🎯 AI 竞争策略建议
体检报告 Tab:
- 🤖 AI 产品健康评估(0-100 分圆环 + 总结)
- 🚨 AI 风险识别(带紧急度标签的风险列表)
- 📦 AI 识别的退货原因
用户洞察 Tab:
- 🤖 AI 用户洞察总结
- 👤 AI 用户画像(3-4 个典型用户群)
- 💡 AI 识别的未满足需求
- 🚀 AI 市场机会
AI 报告卡片使用紫色左边框 + 渐变背景区分,视觉上与本地统计分析明确分层。
七、踩坑记录 & 解决方案
| # | 问题 | 原因 | 解决方案 |
|---|---|---|---|
| 1 | _locales subtree is missing 加载失败 |
manifest 声明了 default_locale 但没创建 _locales 文件夹 |
移除 default_locale 字段 |
| 2 | 评论抓取始终 0 条 | 新版亚马逊把 review-body 的 data-hook 名改了 |
用 [data-hook$="body"] 模糊匹配 + 最长文本兜底 |
| 3 | 面板注入后打不开 | panel.js 有路径白名单 + popup 消息链路不通 | 移除白名单 + 暴露全局 window.__AMZ_IQ_PANEL__ API + popup 多级兜底打开 |
| 4 | AI API 调用 CORS 报错 | content script 无法跨域请求 | 所有 API 调用放到 background Service Worker |
| 5 | Service Worker 里 fetch 也被拦截 | 没有在 host_permissions 里声明 API 域名 |
加上 https://api.openai.com/* 和 https://api.anthropic.com/* |
| 6 | AI 返回的 JSON 解析失败 | 模型有时候用 ` ```json ````包裹输出 | 正则提取 fence 里的内容再 JSON.parse |
| 7 | 部分页面评论区在 iframe 里 | 亚马逊某些布局把评论放在 iframe 中渲染 | 添加 diagnoseDom() 诊断函数检测 iframe 列表 |
八、如何本地运行
# 1. 克隆/下载项目到本地
# 2. 打开 Chrome,访问 chrome://extensions
# 3. 开启右上角「开发者模式」
# 4. 点击「加载已解压的扩展程序」→ 选择项目文件夹
# 5. 右键扩展图标 → 选项 → 填入 API Key
# 6. 打开任意亚马逊商品页 → 点击右下角橙色 IQ 按钮
# 7. 点击「抓取并分析」→ 等待结果
推荐模型配置:
| 模型 | 优势 | 每次成本 |
|---|---|---|
gpt-4o-mini |
性价比最高、速度快 | ≈ ¥0.01 |
gpt-4o |
分析更全面 | ≈ ¥0.05 |
claude-sonnet-4-20250514 |
深度分析、中文好 | ≈ ¥0.03 |
九、总结
这个项目让我深入实践了:
- Chrome Extension MV3 开发全流程(从 manifest 配置到 Service Worker 通信)
- 复杂 DOM 解析的鲁棒性设计(多选择器 + 模糊匹配 + 兜底策略)
- LLM API 工程化接入(prompt 设计、token 控制、JSON 解析容错)
- 页内 UI 注入(CSS 隔离、z-index 管理、抽屉动画)
- 产品思维(不只是技术实现,还要想清楚商业闭环)
如果你也是亚马逊卖家、对 Chrome 扩展开发或 AI 应用感兴趣,欢迎评论区交流!
觉得有帮助的话,点个赞 👍 收藏一下吧!
---
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)