#!/usr/bin/env node /** * 从 3 份 VOC JSON 中提炼用于"复合体方向"分析的关键数据 * - 用户真实原声(Top 评论) * - VOC 主题聚类(痛点/亮点/场景) * - Amazon 对标(品牌分布 / 价位 / 详细产品成分卖点) * - TikTok 关键词 + 作者画像 * - 市场情报:TT Ads 关键词洞察 + Douyin 热榜 * * 输出到 data/voc-summary-for-product-dev.txt,供后续分析 */ const fs = require('fs'); const path = require('path'); const { analyze } = require('./voc-analyze.js'); const PRODUCTS = [ { key: 'liver', label: '江中肝纯片(OTC 保肝片剂)', file: 'jiangzhong-liver-voc.json' }, { key: 'probiotic', label: '江中儿童乳酸菌片', file: 'jiangzhong-probiotic-voc.json' }, { key: 'monkey', label: '江中猴姑饼干', file: 'jiangzhong-monkey-voc.json' }, ]; function formatList(arr, max = 10) { if (!arr || !arr.length) return '(无)'; return arr.slice(0, max).map((x, i) => ` ${String(i + 1).padStart(2, '0')}. ${x}`).join('\n'); } function out(s) { buffer.push(s); } const buffer = []; for (const p of PRODUCTS) { const fp = path.join('data', p.file); if (!fs.existsSync(fp)) { out(`\n\n========== ${p.label} ========== [JSON 不存在]`); continue; } const voc = JSON.parse(fs.readFileSync(fp, 'utf-8')); const A = analyze(voc); out(`\n\n${'='.repeat(80)}`); out(`【${p.label}】 · ${p.file}`); out('='.repeat(80)); // === 基础规模 === out('\n● 规模:'); out(` - ${A.metrics.notes} 篇小红书笔记 · ${A.metrics.sampleComments} 条真实评论 · ${A.kols.length} 位作者画像`); out(` - 点赞 ${A.metrics.totalLikes} · 评论 ${A.metrics.totalComments} · 收藏 ${A.metrics.totalCollected}`); // === 核心洞察 === if (A.coreInsights && A.coreInsights.length) { out('\n● 三条核心洞察:'); A.coreInsights.forEach((ins, i) => { out(` ${i + 1}. ${ins.title || ins.headline || ins}`); if (ins.body || ins.desc) out(` ${(ins.body || ins.desc).slice(0, 200)}`); }); } // === 用户真实原声(高赞 top 15)=== if (A.voiceWall && A.voiceWall.length) { out(`\n● 用户真实原声 (Top ${Math.min(A.voiceWall.length, 12)}):`); A.voiceWall.slice(0, 12).forEach((c, i) => { const content = (c.content || c.text || '').replace(/\s+/g, ' ').slice(0, 120); out(` ${String(i + 1).padStart(2, '0')}. [${c.likes || 0}赞] ${content}`); }); } // === VOC 主题聚类(痛点/亮点/场景)=== if (A.themes) { const renderTheme = (key, title) => { const arr = A.themes[key]; if (!arr || !arr.length) return; out(`\n● ${title}:`); arr.slice(0, 10).forEach((t, i) => { const label = t.label || t.name || t.theme || ''; const freq = t.freq || t.count || t.frequency || 0; const sample = (t.samples || t.examples || [])[0] || ''; out(` ${i + 1}. [${freq}次] ${label}${sample ? ' · 代表原声: ' + String(sample).slice(0, 100) : ''}`); }); }; renderTheme('painPoints', 'VOC 痛点簇'); renderTheme('brightSpots', 'VOC 亮点簇'); renderTheme('scenes', 'VOC 场景簇'); } // === Amazon 对标 === if (A.amazon && !A.amazon.empty) { out('\n● Amazon 对标:'); out(` - ${A.amazon.keywords?.length || 0} 组英文关键词 × ${A.amazon.total || 0} 款产品`); if (A.amazon.topBrands) { out(` - Top 6 品牌:`); (A.amazon.topBrands || []).slice(0, 6).forEach((b, i) => { out(` ${i + 1}. ${b.brand || b[0]} · 销量 ${b.sales || b[1] || 0} · 份额 ${b.share ? b.share.toFixed(1) + '%' : '-'}`); }); } if (A.amazon.priceBuckets) { out(` - 价位分布:`); Object.entries(A.amazon.priceBuckets).forEach(([k, v]) => out(` ${k}: ${v} 款`)); } // Top 6 产品的详细成分/卖点 if (A.amazon.detailProducts) { out(` - 深度详情 Top 6:`); A.amazon.detailProducts.slice(0, 6).forEach((prod, i) => { const title = (prod.title || '').slice(0, 80); const brand = prod.brand || '-'; const price = prod.price || '-'; const rating = prod.rating || '-'; const reviews = prod.reviewCount || prod.ratingsCount || 0; out(` ${i + 1}. [${brand}] ${title}`); out(` $${price} · ★${rating} · ${reviews} 评 · BSR ${prod.bsrRank || '-'}`); }); } // 品牌机会评估 dossier if (A.amazon.dossiers) { out(` - 竞品档案 (dossiers):`); A.amazon.dossiers.slice(0, 4).forEach((d, i) => { out(` ${i + 1}. ${d.brand} (${d.positioning}) · 份额 ${d.share?.toFixed(1)}% · 均价 $${d.avgPrice?.toFixed(1)}`); if (d.strengths?.length) out(` 优势: ${d.strengths.slice(0, 3).map(s => s.label).join(' / ')}`); if (d.gaps?.length) out(` 缝隙: ${d.gaps.slice(0, 3).map(g => g.label).join(' / ')}`); }); } // 机会评估 if (A.amazon.opportunityAssessment) { const op = A.amazon.opportunityAssessment; out(` - 品类机会评估: ${op.grade} (${op.totalScore}/${op.maxScore})`); if (op.dimensions) { op.dimensions.slice(0, 6).forEach((d) => out(` · ${d.name}: ${d.level} · ${(d.note || '').slice(0, 80)}`)); } } } // === TikTok === if (A.tiktok && !A.tiktok.empty) { out('\n● TikTok 海外内容端:'); out(` - 关键词: ${(A.tiktok.keywords || []).join(' / ')}`); out(` - ${A.tiktok.totalVideos || 0} 视频 · ${A.tiktok.totalAuthors || 0} 作者 · ${A.tiktok.totalComments || 0} 评论`); if (A.tiktok.topHashtags) { out(` - 高频 hashtag: ${(A.tiktok.topHashtags || []).slice(0, 10).map(h => '#' + (h.tag || h[0])).join(' ')}`); } if (A.tiktok.topAuthors) { out(` - Top 作者:`); (A.tiktok.topAuthors || []).slice(0, 5).forEach((a, i) => { out(` ${i + 1}. ${a.nickname || a.unique_id || '-'} · ${a.follower_count || 0} 粉 · ${a.video_count || 0} 视频`); }); } } // === Market Intel === if (A.marketIntel && !A.marketIntel.empty) { const mi = A.marketIntel; out('\n● 市场情报 (TT Ads + Douyin 基线):'); if (mi.ttAds?.hasData) { out(` - TT Ads 关键词洞察:`); (mi.ttAds.keywordInsights || []).slice(0, 5).forEach((ki, i) => { out(` ${i + 1}. "${ki.keyword}"`); out(` · 曝光 ${ki.impression || 0} · CTR ${ki.ctr ? (ki.ctr * 100).toFixed(2) + '%' : '-'} · CVR ${ki.cvr ? (ki.cvr * 100).toFixed(2) + '%' : '-'}`); out(` · posts ${ki.postCount || 0} · 变化 ${ki.postChange ? (ki.postChange > 0 ? '+' : '') + (ki.postChange * 100).toFixed(1) + '%' : '-'}`); out(` · 平均 like ${ki.avgLike || 0} · comment ${ki.avgComment || 0} · share ${ki.avgShare || 0}`); }); if (mi.ttAds.relatedKeywords) { out(` - TT Ads 相关关键词网络 (Top 20):`); const rel = mi.ttAds.relatedKeywords.slice(0, 20).map(r => r.keyword || r[0]); out(` ${rel.join(', ')}`); } } if (mi.douyin?.hotWords?.length) { out(` - Douyin 抖音热词 Top 6: ${mi.douyin.hotWords.slice(0, 6).map(w => w.word || w[0]).join(' / ')}`); } if (mi.douyin?.hotChallenges?.length) { out(` - Douyin 热挑战 Top 5: ${mi.douyin.hotChallenges.slice(0, 5).map(c => c.title || c[0]).join(' / ')}`); } if (mi.douyin?.categoryFilterHit !== undefined) { out(` - Douyin 品类过滤命中: ${mi.douyin.categoryFilterHit} 条 (${mi.douyin.categoryFilterHit === 0 ? '品牌蓝海' : '有内容沉淀'})`); } } } const outPath = 'data/voc-summary-for-product-dev.txt'; fs.writeFileSync(outPath, buffer.join('\n'), 'utf-8'); console.log(`\n✅ 摘要写入: ${outPath} (${(fs.statSync(outPath).size / 1024).toFixed(1)}KB)`);