| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #!/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)`);
|