| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178 |
- /**
- * 舒华跑步机 · 四月小红书 KOC 宣发 结案报告生成器
- * 输入: data/raw-merged.json
- * 输出: shuhua-closing-report.html + shuhua-closing-report.md
- *
- * 灵感: jiangzhong-liver-voc-validation-report 暗色主题 + ks-voc-insight-v8 极简卡片
- */
- const fs = require('fs');
- const path = require('path');
- const ROOT = path.resolve(__dirname, '..');
- const DATA = JSON.parse(fs.readFileSync(path.join(ROOT, 'data', 'raw-merged.json'), 'utf8'));
- const OUT_HTML = path.join(ROOT, 'shuhua-closing-report.html');
- const OUT_MD = path.join(ROOT, 'shuhua-closing-report.md');
- const items = DATA.items;
- const num = (v) => Number(v) || 0;
- // ============== 1. 数据汇总 ==============
- const summary = {
- totalKocs: items.length,
- totalSpend: items.reduce((s, x) => s + num(x.priceTotal), 0),
- totalImpressions: items.reduce((s, x) => s + num(x.impressions), 0),
- totalReads: items.reduce((s, x) => s + num(x.reads), 0),
- totalLikes: items.reduce((s, x) => s + num(x.likes), 0),
- totalCollects: items.reduce((s, x) => s + num(x.collects), 0),
- totalComments: items.reduce((s, x) => s + num(x.comments), 0),
- totalEngagement: items.reduce((s, x) => s + num(x.engagement), 0),
- resolved: items.filter((x) => x.noteId).length,
- failed: items.filter((x) => !x.noteId).length,
- withRealComments: items.filter((x) => (x._comments || []).length > 0).length,
- apiComments: items.reduce((s, x) => s + (x._comments || []).length, 0),
- avgFollowers: Math.round(items.reduce((s, x) => s + num(x.followers), 0) / items.length),
- };
- summary.engagementRate = summary.totalReads ? (summary.totalEngagement / summary.totalReads * 100) : 0;
- summary.cpe = summary.totalEngagement ? (summary.totalSpend / summary.totalEngagement) : 0;
- summary.cpm = summary.totalImpressions ? (summary.totalSpend * 1000 / summary.totalImpressions) : 0;
- // 按内容形态分组
- const byType = {};
- for (const r of items) {
- const k = r.contentType || '未分类';
- if (!byType[k]) byType[k] = { count: 0, reads: 0, engagement: 0, spend: 0 };
- byType[k].count++;
- byType[k].reads += num(r.reads);
- byType[k].engagement += num(r.engagement);
- byType[k].spend += num(r.priceTotal);
- }
- const typeStats = Object.entries(byType)
- .map(([k, v]) => ({ type: k, ...v, avgEng: v.count ? Math.round(v.engagement / v.count) : 0, rate: v.reads ? (v.engagement / v.reads * 100) : 0 }))
- .sort((a, b) => b.engagement - a.engagement);
- // 按类目分组
- const byCat = {};
- for (const r of items) {
- const k = r.category || '未分类';
- if (!byCat[k]) byCat[k] = { count: 0, reads: 0, engagement: 0 };
- byCat[k].count++;
- byCat[k].reads += num(r.reads);
- byCat[k].engagement += num(r.engagement);
- }
- const catStats = Object.entries(byCat).map(([k, v]) => ({ category: k, ...v }));
- // ============== 2. 评论数据 ==============
- const allComments = [];
- for (const r of items) {
- for (const c of (r._comments || [])) {
- allComments.push({
- koc: r.name, type: r.contentType,
- content: c.content || '', like: num(c.like_count),
- ip: c.ip_location || '', nick: (c.user && c.user.nickname) || '',
- isSub: false,
- });
- for (const s of (c.sub_comments || [])) {
- allComments.push({
- koc: r.name, type: r.contentType,
- content: s.content || '', like: num(s.like_count),
- ip: '', nick: (s.user && s.user.nickname) || '',
- isSub: true,
- });
- }
- }
- }
- // ============== 噪声识别 + 真实评论筛选 v4 ==============
- const NOISE_RE = /互赞|互助|加油.*互|可以.*点赞|点赞.*返|蹲.*搭子|互粉/;
- const OFFTOPIC_RE = /眼影|口红|睫毛|化妆|分装|借我|借用|护肤|穿搭|开箱|美术生|画的|画得|插画|手工/;
- const PROMO_RE = /推广|求关注|求互|私信|加微|商务合作|接广告|涨粉/;
- const SHILL_RE = /宝子|亲测|无套路|必.{0,2}冲|绝绝子|拉满|薅羊毛|放心冲|闭眼冲|爆棚|颜值直接|姐妹.{0,3}冲|实力宠粉|爆款|0元购|yyds|YYDS|惊艳到|跺脚/;
- const META_KOL_RE = /博主|up主|UP主|接广|涨粉|掉粉|播放/;
- const EMOJI_HEAVY_RE = /(🥬|🥢|🌿|🤩|💯|🔥|💥|✅|💦|📸|🥳|🛒|🎉|✨|💚|❗|‼️)/g;
- const stripDeco = (s) => s.replace(/\[[^\]]+\]/g, '').replace(/[@#][^\s@#]+/g, '').replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '');
- const noiseComments = allComments.filter((c) => NOISE_RE.test(c.content));
- // 跑步机产品强相关词典 - 7 大主题
- const PRODUCT_TOPICS_SHUHUA = {
- '静音减震': /静音|减震|噪音|噪声|声音|分贝|楼下|楼上|邻居|扰邻|商品房|楼板|响|吵|安静/,
- '专业参数': /坡度|速度|心率|配速|马达|马力|功率|参数|配置|续航|履带|跑带|尺寸/,
- '场景体验': /家用|居家|社恐|健身房|减肥|减脂|塑形|课程|训练|跑步|走路|快走/,
- '购买决策': /购买|入手|考虑|对比|划算|性价比|价格|预算|犹豫|推荐|值得|后悔/,
- '使用反馈': /好用|不好用|质量|耐用|结实|稳|抖|坏了|售后|故障|包装|物流|安装/,
- '竞品提及': /易跑|麦瑞克|亿健|岱宇|舒华|小米|华为|keep|Keep/,
- '复购口碑': /用了.*[年月天]|每天|经常|坚持|续费|又买|回头|二次/,
- };
- const PRODUCT_RE_SHUHUA = new RegExp(Object.values(PRODUCT_TOPICS_SHUHUA).map((r) => r.source).join('|'));
- const realCommentsAll = allComments.filter((c) => {
- const txt = c.content || '';
- if (c.nick && c.koc && c.nick === c.koc) return false; // 博主自评
- if (/^\s*@/.test(txt) && stripDeco(txt.replace(/^\s*@[^\s@#]+/, '')).length < 20) return false;
- if (NOISE_RE.test(txt) || OFFTOPIC_RE.test(txt) || PROMO_RE.test(txt) || SHILL_RE.test(txt) || META_KOL_RE.test(txt)) return false;
- const emojis = txt.match(EMOJI_HEAVY_RE) || [];
- if (emojis.length >= 3) return false;
- const core = stripDeco(txt);
- if (core.length < 6) return false;
- if (core.length > 80 && emojis.length >= 1) return false;
- if (core.length > 120) return false;
- return true;
- });
- // 产品强相关优先,但样本小不强制 (允许后补)
- const realComments = realCommentsAll.filter((c) => PRODUCT_RE_SHUHUA.test(c.content));
- const realCommentsFallback = realCommentsAll.filter((c) => !PRODUCT_RE_SHUHUA.test(c.content));
- // 主题分桶 + 信息量排序 + 轮询
- const informationScore = (c) => {
- let hits = 0;
- for (const re of Object.values(PRODUCT_TOPICS_SHUHUA)) if (re.test(c.content)) hits++;
- return hits * 20 + stripDeco(c.content).length;
- };
- const buckets = {};
- for (const tag of Object.keys(PRODUCT_TOPICS_SHUHUA)) buckets[tag] = [];
- for (const c of realComments) {
- for (const [tag, re] of Object.entries(PRODUCT_TOPICS_SHUHUA)) {
- if (re.test(c.content)) { buckets[tag].push(c); break; }
- }
- }
- for (const tag of Object.keys(buckets)) buckets[tag].sort((a, b) => (b.like - a.like) || (informationScore(b) - informationScore(a)));
- const topPicks = [];
- const queues = Object.entries(buckets).map(([tag, list]) => ({ tag, list, idx: 0 }));
- for (let round = 0; round < 4 && topPicks.length < 12; round++) {
- for (const q of queues) {
- if (topPicks.length >= 12) break;
- if (q.idx < q.list.length && q.idx < round + 1) {
- topPicks.push({ topic: q.tag, c: q.list[q.idx] });
- q.idx++;
- }
- }
- }
- // 不够 12 条用 fallback 补
- for (const c of realCommentsFallback.sort((a, b) => b.like - a.like)) {
- if (topPicks.length >= 12) break;
- topPicks.push({ topic: '其他真实声音', c });
- }
- // ============== 3. 话题主题分析 ==============
- const TOPICS = [
- { tag: '减脂/减肥/健身', re: /减肥|减脂|健身|瘦|燃脂|塑形|运动|锻炼/, color: '#00DC82' },
- { tag: '扰邻/减震/楼下', re: /扰民|楼下|减震|噪音|声音|吵|楼板|邻居/, color: '#F5A623' },
- { tag: '参数/坡度/速度/心率', re: /坡度|速度|心率|配速|马力|功率|参数|尺寸|折叠/, color: '#3B82F6' },
- { tag: '社恐/居家/便利', re: /社恐|居家|在家|健身房|懒|方便|便利/, color: '#8B5CF6' },
- { tag: '互动询价/搭子', re: /搭子|互助|互赞|加油|点赞|怎么买|多少钱|链接/, color: '#FF4D8D' },
- { tag: '竞品提及', re: /易跑|麦瑞克|亿健|岱宇|乔山|舒华|SHUA/i, color: '#EF4444' },
- { tag: '效果/见证/打卡', re: /打卡|坚持|天数|月|斤|体重|换头|蜕变|效果/, color: '#06B6D4' },
- ];
- const topicHits = {};
- for (const t of TOPICS) topicHits[t.tag] = [];
- for (const c of allComments) {
- for (const t of TOPICS) if (t.re.test(c.content)) topicHits[t.tag].push(c);
- }
- // ============== 4. 词云数据 ==============
- // 品牌词 (从评论 + 已知投放词单)
- const BRAND_WORDS = ['舒华', 'SHUA', '舒华跑步机', '舒华健身', 'SHUAhome'];
- const ACTIVITY_WORDS = ['新品首发', '618', '直播福利', '领券', '满减', '试用体验', '限时优惠', '打卡返现', '搭子招募'];
- const CATEGORY_WORDS = ['跑步机', '家用跑步机', '折叠跑步机', '静音跑步机', '走步机', '健身器材', '减脂器械', '智能跑步机', '可折叠'];
- // 评论文本词频 — 改为白名单 + 关键词词典匹配 (样本量小时此法最稳)
- const VOC_KEYWORDS = [
- // 品类/场景
- '跑步机', '走步机', '健身房', '健身', '减肥', '减脂', '燃脂', '塑形', '运动', '锻炼', '爬坡', '坡度', '速度', '配速', '心率', '马力', '功率', '折叠', '静音', '减震',
- // 场景痛点
- '楼下', '邻居', '楼板', '扰民', '噪音', '声音', '商品房', '咚咚', '听到', '居家', '在家', '社恐', '搭子',
- // 行为/产品对话
- '体验', '免费', '回放', '拉伸', '打卡', '坚持', '换头', '蜕变', '效果', '便宜', '划算', '价格',
- // 情绪/拟声 (有意义的)
- '加油', '救命', '互助', '互赞', '点赞',
- // 竞品
- '易跑', '麦瑞克', '亿健', '岱宇', '乔山',
- // 品牌 (即使为 0 也展示)
- '舒华', 'SHUA',
- ];
- function termCounts(texts) {
- const c = new Map();
- for (const w of VOC_KEYWORDS) {
- let cnt = 0;
- const re = new RegExp(w, 'gi');
- for (const t of texts) if (t) cnt += (t.match(re) || []).length;
- if (cnt > 0) c.set(w, cnt);
- }
- return [...c.entries()].sort((a, b) => b[1] - a[1]);
- }
- const commentTexts = allComments.map((c) => c.content);
- const wordcloudComments = termCounts(commentTexts);
- // 品牌/活动/品类预制词云 (从评论计数 + 默认基线)
- function presetCloud(words, texts) {
- const out = [];
- const re = (w) => new RegExp(w, 'gi');
- for (const w of words) {
- let cnt = 0;
- for (const t of texts) if (t) cnt += (t.match(re(w)) || []).length;
- // 给未在评论中出现的预定义词一个基线值, 表达 "占位"
- out.push({ name: w, value: cnt > 0 ? cnt + 5 : 1 });
- }
- return out.sort((a, b) => b.value - a.value);
- }
- const cloudBrand = presetCloud(BRAND_WORDS, commentTexts);
- const cloudActivity = presetCloud(ACTIVITY_WORDS, commentTexts);
- const cloudCategory = presetCloud(CATEGORY_WORDS, commentTexts);
- // ============== 5. 优点 / 不足 / 建议 ==============
- const failedNotes = items.filter((x) => !x.noteId);
- const lowReadCnt = items.filter((x) => num(x.reads) < 100).length;
- const lowEngCnt = items.filter((x) => num(x.engagement) < 5).length;
- const noiseRate = allComments.length ? (noiseComments.length / allComments.length * 100) : 0;
- const PROS = [
- { title: '内容形态多样化测试', text: `本期投放跨 ${typeStats.length} 种内容形态 (踩坑反转/效果展示/参数干货/泛流量/疑问互动),为下一轮收敛形态提供 A/B 数据。` },
- { title: '出现真实场景化讨论', text: `评论中出现"坡度 15-20 / 速度 4.2-4.5 / 心率 135-149"等专业参数对话,以及"扰邻焦虑 / 楼板厚度 / 社恐居家"等真实生活场景,**说明素人评论已带出潜客真实痛点**。` },
- { title: '低门槛预算撬动 KOC 矩阵', text: `合计预算 ¥${summary.totalSpend.toLocaleString('zh-CN')} 投放 ${summary.totalKocs} 位 KOC,平均单价 ¥${Math.round(summary.totalSpend / summary.totalKocs)},是性价比极高的"种草起量"试水方案。` },
- ];
- const CONS = [
- { title: '微粉号产出极差', text: `${lowReadCnt}/${summary.totalKocs} 篇阅读 < 100,${lowEngCnt}/${summary.totalKocs} 篇互动 < 5,部分账号粉丝量过低 (平均 ${summary.avgFollowers.toLocaleString('zh-CN')}) 导致曝光天花板很低。` },
- { title: '评论激发率严重不足', text: `仅 ${summary.withRealComments}/${summary.totalKocs} 篇笔记有真实评论 (覆盖率 ${(summary.withRealComments / summary.totalKocs * 100).toFixed(1)}%),且 ${noiseComments.length}/${allComments.length} 条 (${noiseRate.toFixed(1)}%) 为"互赞/互助/搭子"噪声评论,**真正的产品对话稀薄**。` },
- { title: '品牌词曝光基本为零', text: `${allComments.length} 条真实评论中 "舒华 / SHUA" 等品牌词命中频次 ${Math.max(0, (cloudBrand.find((x) => x.name === '舒华')?.value || 0) - 5)} 次,大量评论谈论的是 "易跑 / 健身房 / 减肥" 等品类与竞品话题,**心智渗透远未达成**。` },
- { title: '短链解析失败 + 数据采集时延', text: `${summary.failed}/${summary.totalKocs} 个短链无法解析 (笔记被删/隐藏),建议投放后 24h 内即抓取首版数据备份。` },
- ];
- const RECS = [
- { p: 'P0', t: '提高 KOC 准入门槛', b: '设置粉丝 ≥ 3,000 + 真实健身/减脂内容历史 + 近 3 个月互动率 ≥ 2% 的硬性筛选,**淘汰本期 80% 微粉号**' },
- { p: 'P0', t: '简报模板加入"必出关键词 + 评论 hook"', b: '`减震 / 扰邻 / 静音 / 楼下听不到` 必出 + 配套实拍音频; 评论引导话术 (如"你跑步机最大的烦恼是什么?")' },
- { p: 'P0', t: '内容形态从 5 种收敛到 2 种', b: '保留 `踩坑反转-效果展示融合` + `参数干货` 各 15~20 篇,放弃 `泛流量 / 疑问互动` 等弱形态,形成统计显著样本' },
- { p: 'P1', t: '配套薯条/聚光投流', b: '对 Top 互动笔记 (engagement > 20 的 ~10 篇) 追加 5~10% 预算投流,放大长尾,弥补 KOC 自然流量不足' },
- { p: 'P1', t: '启动竞品对照 VOC 抓取', b: '抓取 易跑 / 麦瑞克 / 亿健 Top 50 笔记评论,建立竞品评论生态对照基线 (样本量 1000+ 评论)' },
- { p: 'P1', t: '建立"扰邻焦虑"专属内容', b: '基于本期"楼板/楼下/邻居"高频痛点,**单独打透"静音减震"卖点的内容线**,匹配公寓 / 楼房用户精准投放' },
- { p: 'P2', t: '搭建评论区运营 SOP', b: '对评论 > 0 的笔记建立"统一回复脚本 (3 类: 询价/扰邻/效果)" + 风险关键词预警 (拉肚子/坏了/退货)' },
- { p: 'P2', t: '建立投后 24h 数据快照', b: '采集脚本固化为定时任务,投后 24h 内即抓取首版数据,避免短链失效/笔记删除导致复盘缺数' },
- ];
- // ============== 5.5 新机会矩阵 (基于评论逐条逆向挖掘) ==============
- const OPPORTUNITIES = [
- {
- id: 'A1', cat: 'A · 产品卖点', p: 'P0', t: '静音减震 RTB 具象化',
- signal: '沐阳 3 连评论 · 商品房+楼板+邻居',
- action: '分贝评测 + 楼板自测指南 + 真实邻居访谈视频三件套,把"静音减震"从形容词变成可信证据',
- why: '"扰邻焦虑"是商品房 / 高层住宅用户购买跑步机最大决策门槛。当前 KOC 笔记停留在"很安静"这种泛形容词,用户依然不敢下单。把抽象承诺翻译成"分贝数 / 楼下邻居反馈视频 / 楼板震动测试"等可见可量化证据,直接拆掉决策最后一道墙。',
- how: [
- '分贝评测视频: 不同档位实测 + 同房间对比 (跑步 vs 洗衣机 vs 电视)',
- '楼板自测指南: 1 张图教用户在自家楼板放杯水/硬币测震动',
- '真实邻居访谈视频: 找 5 位老用户上门拍楼下邻居反馈 (KOL 软文做不到)',
- '官方素材包统一分发,KOC 简报硬性引用 1 个静音 RTB 镜头',
- ],
- outcome: '"扰邻焦虑"评论占比下降 50%,商品房用户转化率 +20-30%,客户咨询从"声音多大"转为"什么时候发货"',
- },
- {
- id: 'A2', cat: 'A · 产品卖点', p: 'P0', t: '坡度参数明牌对比',
- signal: '木塔塔晒坡度 15-20 + 星星不懂星星推易跑"-6 到 26"',
- action: '简报必出"舒华 vs 易跑参数对比表",拦截"易跑"搜索流量,直接挖竞品墙脚',
- why: '17 条评论里"易跑"被自然提及 1 次 = 用户已在对比阶段。健身硬核用户决策依赖参数,但本期 KOC 笔记几乎不晒参数,白白把这部分流量让给了竞品。明牌参数对比 = 拦截"易跑"搜索流量 + 锁定专业人群。',
- how: [
- '简报硬性出"舒华 vs 易跑参数对比表" (坡度/速度/马达/承重/降噪)',
- 'SEO 关键词加投: "易跑跑步机对比" / "易跑值得买吗"',
- '专业 KOL 1-2 篇深度评测,拍真实使用场景',
- '在评论区主动应战: 用户提竞品时官方账号给数据回应',
- ],
- outcome: '拦截 "易跑" 搜索流量 30%,专业用户决策周期 -50%,品牌专业度认知从 60 → 80 分',
- },
- {
- id: 'A3', cat: 'A · 产品卖点', p: 'P0', t: '社恐居家健身专属内容线',
- signal: '星星不懂星星/福建: 社恐+不爱挤健身房',
- action: '5-10 篇专项内容锁定 i 人/社恐/独居场景,占领被易跑先占的细分心智',
- why: '"社恐 / i 人 / 不去健身房" 是 2024-2025 小红书最大居家心智之一。竞品易跑已抢先占位,但市场远未饱和。舒华本身静音 + 折叠属性天然适合居家,只是没有把这个心智专门讲透。',
- how: [
- '5-10 篇专项笔记: 主题"社恐如何在家瘦 30 斤"/"i 人居家健身 30 天"',
- 'KOL 选号偏向"自我表达型 i 人"达人 (粉丝 5k-50k 即可)',
- '内容必含: 不开摄像头 / 不和教练社交 / 自己节奏 3 个心智锚点',
- '配套 SOP: 跑步机自动连接耳机 / App 一键开始训练',
- ],
- outcome: '社恐/居家细分心智份额建立,从竞品手里挖走 10-15% 用户',
- },
- {
- id: 'A4', cat: 'A · 产品卖点', p: 'P1', t: '跑步机 × 课程包绑定',
- signal: '兔子河南: "第一节课/回放课"',
- action: '联名 Keep / 帕梅拉 / 刘畊宏,买机送 1 年课程 VIP,客单价翻 2-3 倍',
- why: '跑步机是"硬件思维",但用户需要的是"训练效果"。捆绑顶流课程包 = 用软件价值溢价硬件,客单价从 2k 翻到 5-6k 不会让用户感到贵,反而觉得"超值"。',
- how: [
- '与 Keep / 帕梅拉 / 刘畊宏 1 家以上签深度合作',
- '买机送 1 年课程 VIP (单买价值 ¥600-1000)',
- '入门款机型搭课程版本独立 SKU,锁定首单转化',
- '蒲公英 KOC 简报必引用"机器+课程"组合卖点',
- ],
- outcome: '客单价 ×2-3,首单转化率 +30%,差异化壁垒 (硬件竞品难以复刻)',
- },
- {
- id: 'B1', cat: 'B · 内容形态', p: 'P1', t: '365 天蜕变长期 IP',
- signal: '兔子湖南: 一年前奶茶不离手 → 一年后敢露肉了"换头"',
- action: '招募 100 位真实用户做 1 年期 KOL,送机 + 月度回访,产出对比照,双 11/618 集中释放',
- why: '"用户真实蜕变" 是跑步机最强转化素材,1 张前后对比照 > 100 篇 KOC 探店。但这种内容需要时间沉淀,不能一次性买。先种树,1 年后大丰收。',
- how: [
- '招募 100 位真实用户做 1 年期 IP (粉丝 1k-50k 不限)',
- '免费送机 + 月度回访,内容创作支持',
- '统一话题 #舒华 365 天蜕变,品牌官方账号集合分发',
- '双 11/618 节点集中释放对比照,做爆款营销',
- ],
- outcome: '1 年后形成 100 个真实蜕变案例,每节点节省广告费 50% 以上,UGC 持续渗透长尾',
- },
- {
- id: 'B2', cat: 'B · 内容形态', p: 'P0', t: 'UGC 参数交流模板',
- signal: '木塔塔: 坡度 15-20/速度 4.2-4.5/心率 135-149',
- action: '简报加入"晒你的训练参数"话题,App 自动生成参数分享卡,自然形成 UGC 素材库',
- why: '"参数交流" 在跑步机社群是最自然的 UGC 形态,但目前几乎没有引导。一条用户晒参数的笔记 = 1 个免费 RTB 锚点,且能引发其他用户参数对比讨论。',
- how: [
- '简报加入"晒你的训练参数"话题,作为加分项',
- 'App 端自动生成训练参数分享卡 (1 键导出图片)',
- '官方账号每周精选"本周最强参数"专题',
- '建立训练参数排行榜,激励用户晒数据',
- ],
- outcome: '免费 UGC 素材库 +50 条/月,品牌专业度持续渗透,长尾 SEO 流量 +20%',
- },
- {
- id: 'B3', cat: 'B · 内容形态', p: 'P0', t: '泛流量型升级为专业体验型',
- signal: '形态错配反向信号: 泛流量型互动最低但产生最高质量评论',
- action: '把"泛流量相关型"重命名为"专业体验交流型",下一轮投入比例从 12% 提到 30%',
- why: '本期最大反直觉信号: "泛流量型" 笔记互动数据最差,但评论区出现的是最专业的用户对话 (参数 / 楼板 / 邻居)。说明这种形态吸引的是"质优"用户而非"量大"用户,只是被低估了。',
- how: [
- '把"泛流量相关型"重命名为"专业体验交流型"',
- '下一轮投入比例从 12% 提到 30%',
- '简报偏向引导用户参数交流 / 真实使用场景',
- '考核指标从"互动率"切到"评论质量分" (专业评论占比)',
- ],
- outcome: '高质量评论占比 +50%,品牌专业人群心智渗透 ×2,长期复购率 +15%',
- },
- {
- id: 'B4', cat: 'B · 内容形态', p: 'P1', t: '真实邻居访谈视频',
- signal: '沐阳云南: 跑步机声 + 邻居反馈"没听到"',
- action: '找 5 位老用户上门,让楼下邻居出镜确认,这是 KOL 软文做不到的真实信任',
- why: 'KOL 说"很安静"用户半信半疑,KOL 楼下邻居说"没听到"用户立刻信任。第三方背书是降低决策门槛最锋利的内容形式。',
- how: [
- '招募 5 位老用户参与"邻居访谈"项目',
- '上门拍摄: 跑步机使用 + 楼下邻居出镜反馈',
- '剪成 1 分钟短视频,小红书 + 视频号同步',
- '门店关键位置二维码引流',
- ],
- outcome: '"扰邻焦虑"心理门槛进一步降低,商品房用户决策周期 -30%',
- },
- {
- id: 'C1', cat: 'C · 人群渠道', p: 'P0', t: 'KOC 性别/年龄结构调整',
- signal: '本期 43 位 KOC 全为萌系女性昵称,跑步机决策人群错位',
- action: '男性 30% + 宝爸宝妈 20% + 30+ 中产女性 10%,等于换一批用户',
- why: '跑步机决策人 ≠ 萌系女性。家庭购买决策更多由男性 / 宝爸宝妈 / 30+ 中产驱动。当前 KOC 全为单身年轻女性,看起来"可爱"但不是真实购买人群,转化率天然低。',
- how: [
- 'KOC 选号比例: 男性 30% + 宝爸宝妈 20% + 30+ 中产女性 10% + 年轻女性 40%',
- '内容形态适配: 男性偏参数评测 / 宝爸宝妈偏家庭场景 / 中产偏品质生活',
- '画像审核: 选号时验证粉丝主体年龄性别,避免"号是中产但粉丝是大学生"',
- '建立 KOC 多维度黑灰白名单',
- ],
- outcome: '决策人群错位被纠正,到店/到电商转化率 +30-50%',
- },
- {
- id: 'C2', cat: 'C · 人群渠道', p: 'P1', t: '商品房新业主精准包',
- signal: '沐阳: "商品房 / 开发商问题"',
- action: '定向 3 年内交付的高层公寓用户,这是扰邻焦虑最强的目标人群',
- why: '商品房新业主 = 刚装修完 + 有居家运动需求 + 最在意扰邻 = 跑步机最优潜在客户群。目前没有任何渠道精准触达,纯靠泛流量碰运气。',
- how: [
- '与房产 KOC / 装修 KOC 合作,精准触达交付 3 年内业主',
- '与房地产物业合作: 业主群发"扰邻友好家电推荐"',
- '小红书"装修笔记"达人投放,植入跑步机',
- '高层公寓集中区域线下广告 (电梯框架 / 社区入口)',
- ],
- outcome: '高意向商品房新业主触达 +1000 起步,客单价高于均值',
- },
- {
- id: 'C3', cat: 'C · 人群渠道', p: 'P1', t: '减肥搭子社交营 (噪声资产化)',
- signal: '47% 互助互赞噪声实为真实减肥群体寻找搭子',
- action: '#舒华 30 天减肥搭子营 官方话题 + 企微私域 + 月度 PK 赛事,把噪声变长效资产',
- why: '本期评论里 47% 互赞互助 "噪声",其实是真实的减肥群体在寻找运动搭子。把"噪声"变成"社群资产" = 把流量变成用户。',
- how: [
- '推 #舒华 30 天减肥搭子营 官方话题 (公司账号背书)',
- '小红书群 + 企微私域承接报名',
- '月度 PK 赛事 + 实物奖励 (每月轻奢 SKU)',
- '完赛用户给优惠 / 老带新返利',
- ],
- outcome: '私域用户 +5000 起步,长期复购率 ×2,内容生态自循环',
- },
- {
- id: 'C4', cat: 'C · 人群渠道', p: 'P0', t: '一线 + 新一线 IP 占比 ≥ 50%',
- signal: '本期评论 IP 缺京沪深广杭蓉',
- action: '跑步机是大件家居,一线城市才有支付力 + 居住空间,选号必须明确 IP 配比',
- why: '跑步机客单价 2k+ 是大件家居,需要支付力 + 居住空间。一线/新一线人群是核心。本期 IP 严重缺一线,投放打到了价格敏感人群。',
- how: [
- 'KOC 选号硬性规定: 一线 + 新一线 IP 占比 ≥ 50% (北上广深 + 杭州/成都/武汉)',
- 'IP 验证作为蒲公英结案核心指标',
- '一线城市同步投放线下广告 (社区/健身房/物业)',
- '新一线节点城市做品牌活动',
- ],
- outcome: '客单价 +15-20%,触达决策人群更精准,品牌势能提升',
- },
- {
- id: 'D1', cat: 'D · 投放机制', p: 'P0', t: '类目标签从家居/好物迁到健身/减脂',
- signal: '本期挂"家居 22 + 好物 21",但搜索词是"跑步机推荐/家用跑步机"',
- action: '简报锁定 SEO 标签 居家健身 / 减脂塑形 / 跑步机推荐 / 健身房替代',
- why: '"家居/好物"标签竞争激烈且与"跑步机"心智弱关联;"健身/减脂/居家健身"才是用户真实搜索路径。换标签 = 换流量池,免费降本。',
- how: [
- '简报硬性要求: 标签必含"居家健身/减脂塑形/跑步机推荐/健身房替代"',
- '禁用"家居好物"等泛标签',
- '关键词扩展: "家用跑步机选购" / "小户型跑步机" 等长尾词',
- '考核 SEO 流量入口占比 ≥ 30%',
- ],
- outcome: 'SEO 流量入口 +50-100%,搜索流量获客成本下降 30%',
- },
- {
- id: 'D2', cat: 'D · 投放机制', p: 'P1', t: 'MCN 来源审计 + 多源选号',
- signal: '粉丝量 1k-2k 高度同质,疑似单一 MCN 包号',
- action: '≥ 3 家 MCN + ≥ 20% 蒲公英直选 + ≥ 10% 自建池 + 粉丝阶梯化金字塔结构',
- why: '本期 KOC 粉丝量过度集中 1k-2k,疑似单一 MCN 提供"扁平池",这种号有刷数据嫌疑且互动质量低。多 MCN + 直选打散来源,保证内容生态多样性。',
- how: [
- '≥ 3 家不同 MCN 提供候选号',
- '≥ 20% 蒲公英直选 (跳过 MCN)',
- '≥ 10% 自建 KOC 池 (品牌培育)',
- '粉丝量阶梯: 头部 5% / 腰部 30% / 尾部 65%',
- ],
- outcome: '内容生态多样性提升,刷量风险下降,长尾流量稳定',
- },
- {
- id: 'D3', cat: 'D · 投放机制', p: 'P2', t: '7 天上门试驾 O2O',
- signal: '星星不懂星星山东: "免费体验欢迎来锻炼"',
- action: '借鉴戴森/特斯拉,跑步机 7 天上门 + 不满意退款,降低决策门槛,KOC 矩阵推广',
- why: '跑步机决策成本高 (大件 + 占地 + 长期使用),7 天试驾 = 把决策门槛拆到地板。戴森吸尘器 / 特斯拉试驾都是验证过的成熟模型。',
- how: [
- '7 天上门试驾, 不满意 100% 退款',
- 'KOC 矩阵推广"试用日记"内容',
- '配套售后 SOP: 退货免费上门取',
- '小红书 / 抖音"7 天试驾打卡"话题运营',
- ],
- outcome: '决策门槛大幅降低,转化率 ×1.5-2,试驾用户复购率 +50%',
- },
- {
- id: 'E1', cat: 'E · 数据机制', p: 'P0', t: '投后 24h 抓取 + 博主行为预警',
- signal: 'xlsx 19 评论 → API 17, 缺失 2 条 (可能博主自删)',
- action: '24h 内首版数据快照,捕捉删评/删笔记信号,识别评论区翻车风险',
- why: '本次复盘发现 xlsx 报备 19 条评论 → API 实际抓到 17 条,差额 2 条可能是博主自删。这是评论区出现负面/翻车的强信号,但我们目前无法及时发现。',
- how: [
- '采集脚本固化为 24h 自动定时任务',
- '建立"博主自删评论"预警 (报备 vs 实抓差额 ≥ 3 即告警)',
- '对应 KOC 客服跟进核实是否有翻车',
- '建立长期 KOC 风险数据库',
- ],
- outcome: '评论区翻车从"事后才知道"变成"6h 内介入",品牌信任度兜底',
- },
- {
- id: 'E2', cat: 'E · 数据机制', p: 'P1', t: '3 天数据保护期 + 死笔记自动补流',
- signal: '11/43 篇互动 < 5,33/43 篇产出极差 = ¥7000+ 浪费',
- action: '投后 3 天数据 < 阈值的笔记,自动触发 ¥30-50 薯条二次投流补救,而非直接放弃',
- why: '本期 11/43 篇互动 < 5,长尾零产出占 26%,这部分预算几乎是沉没成本。机制化止损 + 二次投流 = 把死笔记救回来。',
- how: [
- '投后 72h 自动检查互动数据',
- '互动 < 5: 自动追加 ¥30-50 薯条二次抢救',
- '抢救后仍 < 10: 标记 KOC 为低效 (3 次失败拉黑)',
- '建立 KOC 历史投放表现数据库',
- ],
- outcome: '长尾零互动篇数下降 30-50%,投放 ROI 持续优化',
- },
- ];
- const TOP5 = ['A1', 'A2', 'C1', 'B3', 'E1'];
- // ============== 6. 渲染 HTML ==============
- const fmt = (n) => Number(n || 0).toLocaleString('zh-CN');
- const pct = (n) => Number(n || 0).toFixed(2) + '%';
- const esc = (s) => String(s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
- const detailRows = [...items].sort((a, b) => num(b.engagement) - num(a.engagement)).map((r, i) => `
- <tr>
- <td class="num">${i + 1}</td>
- <td>${esc(r.name)}</td>
- <td><span class="tag gray">${esc(r.category || '-')}</span></td>
- <td><span class="tag">${esc(r.contentType || '-')}</span></td>
- <td class="num mono">${fmt(r.followers)}</td>
- <td class="num mono">¥${fmt(r.priceTotal)}</td>
- <td class="num mono">${fmt(r.impressions)}</td>
- <td class="num mono">${fmt(r.reads)}</td>
- <td class="num mono">${fmt(r.likes)}</td>
- <td class="num mono">${fmt(r.collects)}</td>
- <td class="num mono">${fmt(r.comments)}</td>
- <td class="num mono ${num(r.engagement) === 0 ? 'dim' : ''}">${fmt(r.engagement)}</td>
- <td>${r.noteId ? '<span class="tag green">已解析</span>' : '<span class="tag rose">短链失效</span>'}</td>
- </tr>`).join('');
- const topicRows = TOPICS.map((t) => {
- const hits = topicHits[t.tag];
- const sample = hits.sort((a, b) => b.like - a.like)[0];
- return `<tr>
- <td><span style="display:inline-block; width:8px; height:8px; border-radius:50%; background:${t.color}; margin-right:8px; vertical-align:middle"></span>${esc(t.tag)}</td>
- <td class="num mono">${hits.length}</td>
- <td class="num mono">${(hits.length / Math.max(allComments.length, 1) * 100).toFixed(1)}%</td>
- <td class="sample">${sample ? `<span class="text-xs text-3">[${esc(sample.koc)}@${esc(sample.ip || '-')}]</span> ${esc(sample.content.replace(/\n/g, ' ').slice(0, 80))}${sample.content.length > 80 ? '…' : ''}` : '<span class="text-3">-</span>'}</td>
- </tr>`;
- }).join('');
- const realCommentList = topPicks.map(({ topic, c }) => `
- <div class="quote">
- <div class="quote-meta"><span class="tag green">${esc(topic)}</span> <span class="tag gray">${esc(c.koc)}</span> <span class="text-xs text-3">${esc(c.ip || '')}</span></div>
- <div class="quote-text">${esc(c.content.replace(/\n/g, ' '))}</div>
- </div>`).join('');
- const HTML = `<!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
- <title>舒华跑步机 · 四月小红书 KOC 宣发结案报告</title>
- <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/echarts-wordcloud@2.1.0/dist/echarts-wordcloud.min.js"></script>
- <style>
- :root {
- --bg-0: #0A0A0A; --bg-1: #111111; --bg-2: #1A1A1A; --bg-3: #252525;
- --border: rgba(255,255,255,0.08); --border-strong: rgba(255,255,255,0.16);
- --text-1: #F5F5F5; --text-2: #A8A8A8; --text-3: #6B6B6B;
- --amber: #F5A623; --green: #00DC82; --purple: #8B5CF6; --rose: #FF4D8D; --blue: #3B82F6; --red: #EF4444;
- --font-head: 'Inter','Noto Sans SC','PingFang SC','Microsoft YaHei',system-ui,sans-serif;
- --font-body: 'Noto Sans SC','Inter','PingFang SC','Microsoft YaHei',system-ui,sans-serif;
- --font-mono: 'JetBrains Mono','SF Mono',Consolas,monospace;
- }
- * { margin: 0; padding: 0; box-sizing: border-box; }
- html { scroll-behavior: smooth; }
- body { font-family: var(--font-body); background: var(--bg-0); color: var(--text-1); line-height: 1.65; -webkit-font-smoothing: antialiased; overflow-x: hidden; }
- body::before { content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 0;
- background: radial-gradient(ellipse 900px 700px at 20% 25%, rgba(245,166,35,0.08), transparent 60%),
- radial-gradient(ellipse 800px 600px at 80% 75%, rgba(139,92,246,0.06), transparent 60%); }
- main { position: relative; z-index: 1; }
- ::selection { background: var(--amber); color: #000; }
- section { min-height: 100vh; padding: clamp(60px, 10vh, 120px) clamp(24px, 6vw, 80px); border-bottom: 1px solid var(--border); display: flex; flex-direction: column; justify-content: center; position: relative; }
- section .inner { width: 100%; max-width: 1280px; margin: 0 auto; }
- section::before { content: attr(data-num); position: absolute; top: 32px; right: 60px; font-family: var(--font-mono); font-weight: 600; font-size: 0.78rem; letter-spacing: 0.25em; color: var(--text-3); }
- .eyebrow { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--amber); font-weight: 500; margin-bottom: 18px; }
- .eyebrow::before { content: ''; display: inline-block; width: 24px; height: 1px; background: var(--amber); }
- .h0 { font-family: var(--font-head); font-weight: 900; letter-spacing: -0.04em; line-height: 0.95; font-size: clamp(3rem, 8vw, 6rem); }
- .h1 { font-family: var(--font-head); font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; font-size: clamp(2rem, 4vw, 3rem); margin-bottom: 16px; }
- .h2 { font-family: var(--font-head); font-weight: 700; font-size: clamp(1.4rem, 2.4vw, 1.8rem); margin: 32px 0 16px; }
- .lead { color: var(--text-2); font-size: 1.05rem; max-width: 720px; margin-top: 18px; line-height: 1.8; }
- .sub { color: var(--text-2); margin-bottom: 32px; max-width: 800px; }
- .text-3 { color: var(--text-3); }
- .text-xs { font-size: 0.74rem; }
- .text-sm { font-size: 0.85rem; }
- .mono { font-family: var(--font-mono); }
- .dim { color: var(--text-3); }
- .grid { display: grid; gap: 22px; }
- .grid-2 { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }
- .grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
- .grid-4 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
- .card { background: linear-gradient(180deg, rgba(255,255,255,0.025) 0%, rgba(255,255,255,0.005) 100%), var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 28px; transition: transform 0.3s, border-color 0.3s; }
- .card:hover { transform: translateY(-3px); border-color: var(--border-strong); }
- .card-accent { border-left: 3px solid var(--amber); }
- .card-green { border-left: 3px solid var(--green); }
- .card-rose { border-left: 3px solid var(--rose); }
- .card-blue { border-left: 3px solid var(--blue); }
- .metric { background: var(--bg-1); border: 1px solid var(--border); border-radius: 12px; padding: 24px; position: relative; overflow: hidden; min-width: 0; }
- .metric::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, var(--amber), transparent); opacity: 0.6; }
- .metric-label { font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--text-3); margin-bottom: 10px; }
- .metric-value { font-family: var(--font-head); font-weight: 800; font-size: clamp(1.6rem, 2.6vw, 2.3rem); letter-spacing: -0.03em; line-height: 1.05; word-break: break-all; }
- .metric-unit { font-family: var(--font-mono); font-size: 0.85rem; color: var(--amber); font-weight: 500; margin-left: 4px; }
- .metric-sub { margin-top: 14px; font-size: 0.82rem; color: var(--text-2); line-height: 1.5; }
- .tag { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 4px; font-size: 0.72rem; font-weight: 500; background: rgba(245,166,35,0.1); color: var(--amber); border: 1px solid rgba(245,166,35,0.22); }
- .tag.green { background: rgba(0,220,130,0.08); color: var(--green); border-color: rgba(0,220,130,0.2); }
- .tag.purple { background: rgba(139,92,246,0.08); color: var(--purple); border-color: rgba(139,92,246,0.2); }
- .tag.rose { background: rgba(255,77,141,0.08); color: var(--rose); border-color: rgba(255,77,141,0.2); }
- .tag.blue { background: rgba(59,130,246,0.08); color: var(--blue); border-color: rgba(59,130,246,0.2); }
- .tag.gray { background: rgba(255,255,255,0.04); color: var(--text-2); border-color: var(--border); }
- table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
- th, td { padding: 10px 12px; border-bottom: 1px solid var(--border); text-align: left; }
- th { color: var(--text-3); font-weight: 500; font-size: 0.74rem; letter-spacing: 0.06em; text-transform: uppercase; background: var(--bg-2); position: sticky; top: 0; z-index: 1; }
- td.num, th.num { text-align: right; }
- tr:hover td { background: rgba(255,255,255,0.025); }
- td.sample { color: var(--text-2); font-size: 0.82rem; max-width: 380px; }
- .scroll-table { max-height: 70vh; overflow: auto; border: 1px solid var(--border); border-radius: 12px; background: var(--bg-1); }
- .scroll-table::-webkit-scrollbar { width: 8px; height: 8px; }
- .scroll-table::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: 4px; }
- .chart { width: 100%; height: 360px; }
- .chart-tall { width: 100%; height: 460px; }
- .quote { background: var(--bg-1); border-left: 3px solid var(--amber); border-radius: 0 8px 8px 0; padding: 14px 18px; margin-bottom: 12px; }
- .quote-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
- .quote-text { color: var(--text-1); font-size: 0.94rem; line-height: 1.65; }
- .rec-row { display: flex; gap: 18px; padding: 16px 0; border-bottom: 1px solid var(--border); align-items: flex-start; }
- .rec-row:last-child { border-bottom: none; }
- .rec-p { flex-shrink: 0; width: 48px; font-family: var(--font-mono); font-weight: 700; font-size: 0.9rem; padding: 6px 10px; border-radius: 4px; text-align: center; }
- .rec-p.P0 { background: rgba(255,77,141,0.1); color: var(--rose); border: 1px solid rgba(255,77,141,0.3); }
- .rec-p.P1 { background: rgba(245,166,35,0.1); color: var(--amber); border: 1px solid rgba(245,166,35,0.3); }
- .rec-p.P2 { background: rgba(139,92,246,0.1); color: var(--purple); border: 1px solid rgba(139,92,246,0.3); }
- .rec-content h4 { font-size: 1.05rem; margin-bottom: 6px; }
- .rec-content p { color: var(--text-2); font-size: 0.9rem; line-height: 1.65; }
- .cover { background: radial-gradient(ellipse 60% 80% at 30% 30%, rgba(245,166,35,0.12) 0%, transparent 70%), radial-gradient(ellipse 40% 60% at 80% 70%, rgba(139,92,246,0.06) 0%, transparent 70%), var(--bg-0); }
- .cover-meta { display: flex; gap: 32px; margin-top: 32px; flex-wrap: wrap; }
- .cover-meta-item { font-family: var(--font-mono); font-size: 0.85rem; color: var(--text-2); }
- .cover-meta-item strong { color: var(--text-1); font-weight: 600; display: block; margin-top: 4px; font-size: 1.1rem; }
- .toc { display: flex; gap: 14px; margin-top: 48px; flex-wrap: wrap; }
- .toc a { padding: 8px 16px; border: 1px solid var(--border); border-radius: 100px; color: var(--text-2); font-size: 0.85rem; transition: all 0.2s; cursor: pointer; text-decoration: none; }
- .toc a:hover { border-color: var(--amber); color: var(--amber); }
- @media (max-width: 768px) {
- section { padding: 80px 20px; min-height: auto; }
- .h0 { font-size: 2.5rem; }
- table { font-size: 0.74rem; }
- td, th { padding: 6px 8px; }
- }
- </style>
- </head>
- <body>
- <main>
- <!-- ============= 封面 ============= -->
- <section class="cover" data-num="00 / COVER">
- <div class="inner">
- <div class="eyebrow">SHUA · 跑步机 · KOC 宣发结案 · 2026.04</div>
- <h1 class="h0">舒华跑步机<br/>四月小红书 KOC 宣发<br/><span style="color:var(--amber)">结案报告</span></h1>
- <p class="lead">基于蒲公英 ${summary.totalKocs} 位 KOC 报备数据 + 公开评论真实抓取,完整复盘投放规模、内容形态、互动效率、评论 VOC 与品牌词渗透,并给出下一轮可执行的优化建议。</p>
- <div class="cover-meta">
- <div class="cover-meta-item">投放期间<strong>2026-04</strong></div>
- <div class="cover-meta-item">KOC 数量<strong>${summary.totalKocs} 位</strong></div>
- <div class="cover-meta-item">总预算<strong>¥${fmt(summary.totalSpend)}</strong></div>
- <div class="cover-meta-item">总曝光<strong>${fmt(summary.totalImpressions)}</strong></div>
- <div class="cover-meta-item">总互动<strong>${fmt(summary.totalEngagement)}</strong></div>
- <div class="cover-meta-item">真实评论<strong>${allComments.length} 条</strong></div>
- </div>
- <div class="toc">
- <a href="#sec-1">① 数据汇总</a>
- <a href="#sec-2">② 数据明细</a>
- <a href="#sec-3">③ 话题数据</a>
- <a href="#sec-4">④ 品牌相关词</a>
- <a href="#sec-5">⑤ 优点 / 不足 / 建议</a>
- <a href="#sec-6" style="border-color:var(--rose);color:var(--rose)">⑥ 新机会挖掘 ★</a>
- </div>
- </div>
- </section>
- <!-- ============= 1. 数据汇总 ============= -->
- <section id="sec-1" data-num="01 / SUMMARY">
- <div class="inner">
- <div class="eyebrow">Section 01</div>
- <h2 class="h1">数据汇总 — 投放规模与产出效率</h2>
- <p class="sub">本期 ${summary.totalKocs} 位 KOC,合计预算 ¥${fmt(summary.totalSpend)},总曝光 ${fmt(summary.totalImpressions)} / 总阅读 ${fmt(summary.totalReads)} / 总互动 ${fmt(summary.totalEngagement)},整体互动率 ${pct(summary.engagementRate)}。</p>
- <div class="grid grid-4">
- <div class="metric"><div class="metric-label">投放 KOC</div><div class="metric-value">${summary.totalKocs}<span class="metric-unit">位</span></div><div class="metric-sub">家居 ${catStats.find(c=>c.category==='家居')?.count||0} · 好物 ${catStats.find(c=>c.category==='好物')?.count||0}</div></div>
- <div class="metric"><div class="metric-label">总预算</div><div class="metric-value">¥${fmt(summary.totalSpend)}</div><div class="metric-sub">单价均值 ¥${Math.round(summary.totalSpend / summary.totalKocs)}</div></div>
- <div class="metric"><div class="metric-label">总曝光</div><div class="metric-value">${fmt(summary.totalImpressions)}</div><div class="metric-sub">CPM ¥${summary.cpm.toFixed(2)}</div></div>
- <div class="metric"><div class="metric-label">总阅读</div><div class="metric-value">${fmt(summary.totalReads)}</div><div class="metric-sub">阅读率 ${(summary.totalReads/Math.max(summary.totalImpressions,1)*100).toFixed(1)}%</div></div>
- <div class="metric"><div class="metric-label">总互动</div><div class="metric-value">${fmt(summary.totalEngagement)}</div><div class="metric-sub">CPE ¥${summary.cpe.toFixed(2)}</div></div>
- <div class="metric"><div class="metric-label">点赞</div><div class="metric-value">${fmt(summary.totalLikes)}</div><div class="metric-sub">占互动 ${(summary.totalLikes/Math.max(summary.totalEngagement,1)*100).toFixed(1)}%</div></div>
- <div class="metric"><div class="metric-label">收藏</div><div class="metric-value">${fmt(summary.totalCollects)}</div><div class="metric-sub">深度兴趣信号</div></div>
- <div class="metric"><div class="metric-label">评论</div><div class="metric-value">${fmt(summary.totalComments)}<span class="metric-unit">/ ${allComments.length} 抓取</span></div><div class="metric-sub">评论激发率偏低</div></div>
- </div>
- <h3 class="h2">内容形态产出对比</h3>
- <div class="grid grid-2">
- <div class="card"><div id="chart-type-engagement" class="chart"></div></div>
- <div class="card"><div id="chart-type-rate" class="chart"></div></div>
- </div>
- </div>
- </section>
- <!-- ============= 2. 数据明细 ============= -->
- <section id="sec-2" data-num="02 / DETAIL">
- <div class="inner">
- <div class="eyebrow">Section 02</div>
- <h2 class="h1">数据明细 — 全 ${summary.totalKocs} 位 KOC 投放表</h2>
- <p class="sub">按总互动数降序排列。原始 Excel 数据 + 短链解析后的真实笔记 ID + 公开评论数据合并展示。</p>
- <div class="scroll-table">
- <table>
- <thead><tr>
- <th class="num">#</th><th>KOC</th><th>类目</th><th>内容形态</th>
- <th class="num">粉丝</th><th class="num">单价</th>
- <th class="num">曝光</th><th class="num">阅读</th>
- <th class="num">点赞</th><th class="num">收藏</th><th class="num">评论</th><th class="num">互动</th>
- <th>笔记状态</th>
- </tr></thead>
- <tbody>${detailRows}</tbody>
- </table>
- </div>
- </div>
- </section>
- <!-- ============= 3. 话题数据 ============= -->
- <section id="sec-3" data-num="03 / TOPICS">
- <div class="inner">
- <div class="eyebrow">Section 03</div>
- <h2 class="h1">话题数据 — 评论 VOC 主题分布</h2>
- <p class="sub">基于 ${allComments.length} 条真实评论 (含 ${noiseComments.length} 条互助互赞噪声 = ${noiseRate.toFixed(1)}%),按 ${TOPICS.length} 个主题进行规则化标注。</p>
- <div class="grid grid-2">
- <div class="card"><div id="chart-topics" class="chart-tall"></div></div>
- <div class="card">
- <h3 class="h2" style="margin-top:0">主题命中明细</h3>
- <table>
- <thead><tr><th>主题</th><th class="num">命中</th><th class="num">占比</th><th>典型样本</th></tr></thead>
- <tbody>${topicRows}</tbody>
- </table>
- </div>
- </div>
- <h3 class="h2">真实评论原声 (Top ${topPicks.length})</h3>
- <p class="sub">产品强相关 · 多主题轮询 · 已剔除噪声/托式营销/博主自评,展示具有产品对话价值的真实评论。</p>
- <div class="grid grid-2">${realCommentList}</div>
- </div>
- </section>
- <!-- ============= 4. 品牌相关词存量 ============= -->
- <section id="sec-4" data-num="04 / WORDS">
- <div class="inner">
- <div class="eyebrow">Section 04</div>
- <h2 class="h1">品牌相关词存量 — 心智渗透盘点</h2>
- <p class="sub">从评论文本 + 投放预定关键词清单中提取,显示当前品牌词、活动词、品类词在用户对话中的实际渗透情况,以及笔记元数据词云。</p>
- <div class="grid grid-2">
- <div class="card card-accent">
- <h3 class="h2" style="margin-top:0">① 品牌词</h3>
- <p class="text-sm text-3">舒华 / SHUA / 舒华跑步机 等核心品牌词</p>
- <div id="cloud-brand" class="chart"></div>
- </div>
- <div class="card card-green">
- <h3 class="h2" style="margin-top:0">② 活动相关词</h3>
- <p class="text-sm text-3">新品首发 / 618 / 直播福利 / 领券 等本期投放预制活动词</p>
- <div id="cloud-activity" class="chart"></div>
- </div>
- <div class="card card-blue">
- <h3 class="h2" style="margin-top:0">③ 品类词占位</h3>
- <p class="text-sm text-3">跑步机 / 折叠 / 静音 / 走步机 等品类心智词</p>
- <div id="cloud-category" class="chart"></div>
- </div>
- <div class="card card-rose">
- <h3 class="h2" style="margin-top:0">④ 评论高频词云</h3>
- <p class="text-sm text-3">从全部评论文本提取的中文高频 2~3 字词组</p>
- <div id="cloud-comments" class="chart"></div>
- </div>
- </div>
- <h3 class="h2">关键洞察</h3>
- <div class="grid grid-3">
- <div class="card card-rose">
- <div class="tag rose">⚠️ 品牌词渗透不足</div>
- <p style="margin-top:14px;color:var(--text-2)">"舒华/SHUA" 在评论中出现频次极低,用户更多在谈论"易跑/麦瑞克"等竞品和"健身房/减肥"等通用品类话题。</p>
- </div>
- <div class="card card-accent">
- <div class="tag">⚠ 活动词记忆点散</div>
- <p style="margin-top:14px;color:var(--text-2)">没有形成统一可记忆的活动钩子,KOC 笔记 hook 太分散,建议下一轮锁定 1~2 个活动主张。</p>
- </div>
- <div class="card card-green">
- <div class="tag green">✓ 品类词承载明确</div>
- <p style="margin-top:14px;color:var(--text-2)">"跑步机"作为品类词在用户语境中清晰存在,应捆绑"静音/减震/折叠"3 大附属词形成差异化。</p>
- </div>
- </div>
- </div>
- </section>
- <!-- ============= 5. 优点 / 不足 / 建议 ============= -->
- <section id="sec-5" data-num="05 / VERDICT">
- <div class="inner">
- <div class="eyebrow">Section 05</div>
- <h2 class="h1">本次宣发的优点、不足 & 后续投放建议</h2>
- <h3 class="h2"><span class="tag green">✓ 优点</span></h3>
- <div class="grid grid-3">
- ${PROS.map((p) => `<div class="card card-green"><h4 style="margin-bottom:10px;color:var(--green)">${esc(p.title)}</h4><p style="color:var(--text-2);font-size:0.9rem">${p.text}</p></div>`).join('')}
- </div>
- <h3 class="h2"><span class="tag rose">✗ 不足</span></h3>
- <div class="grid grid-2">
- ${CONS.map((c) => `<div class="card card-rose"><h4 style="margin-bottom:10px;color:var(--rose)">${esc(c.title)}</h4><p style="color:var(--text-2);font-size:0.9rem">${c.text}</p></div>`).join('')}
- </div>
- <h3 class="h2"><span class="tag">→ 后续投放建议</span></h3>
- <div class="card">
- ${RECS.map((r) => `<div class="rec-row"><div class="rec-p ${r.p}">${r.p}</div><div class="rec-content"><h4>${esc(r.t)}</h4><p>${r.b}</p></div></div>`).join('')}
- </div>
- <h3 class="h2">下一轮预算建议分配</h3>
- <div class="grid grid-4">
- <div class="metric"><div class="metric-label">头 / 腰部 KOL</div><div class="metric-value">40<span class="metric-unit">%</span></div><div class="metric-sub">2~3 位垂类健身/减脂 KOL,粉丝 ≥ 10万,单篇深度内容</div></div>
- <div class="metric"><div class="metric-label">优质 KOC 矩阵</div><div class="metric-value">35<span class="metric-unit">%</span></div><div class="metric-sub">25~30 篇,粉丝 ≥ 3,000,2 种形态各 15 篇</div></div>
- <div class="metric"><div class="metric-label">薯条 / 聚光投流</div><div class="metric-value">20<span class="metric-unit">%</span></div><div class="metric-sub">追加 Top 互动笔记,放大长尾流量</div></div>
- <div class="metric"><div class="metric-label">评论区运营 + 数据</div><div class="metric-value">5<span class="metric-unit">%</span></div><div class="metric-sub">SOP 话术 + 风险词预警 + 投后 24h 抓取</div></div>
- </div>
- </div>
- </section>
- <!-- ============= 6. 新机会挖掘 ============= -->
- <section id="sec-6" data-num="06 / OPPORTUNITIES">
- <div class="inner">
- <div class="eyebrow" style="color:var(--rose)">Section 06 · ★ 重中之重</div>
- <h2 class="h1">新机会挖掘 — 从 ${allComments.length} 条评论逆向反推 ${OPPORTUNITIES.length} 个新机会</h2>
- <p class="sub">**结案报告告诉老板"过去花得值不值",本节告诉团队"下一步该怎么花得更值"。** 把每一条评论当成一次市场对话逐字解读,从微观信号反推产品/内容/人群/投放/数据 5 大象限的机会缺口。完整逐条解读见配套文档 <a href="./shuhua-new-opportunities.md" style="color:var(--amber);text-decoration:underline">shuhua-new-opportunities.md</a>。</p>
- <h3 class="h2">⭐ Top 5 P0 优先级 (下周可启动)</h3>
- <div class="grid grid-3">
- ${TOP5.map((id, idx) => {
- const o = OPPORTUNITIES.find((x) => x.id === id);
- return `<div class="card card-rose" style="position:relative">
- <div style="position:absolute;top:14px;right:18px;font-family:var(--font-mono);font-size:1.6rem;font-weight:800;color:var(--rose);opacity:0.6">#${idx + 1}</div>
- <div class="tag rose" style="margin-bottom:10px">${o.id} · ${o.p}</div>
- <h4 style="font-size:1.1rem;margin-bottom:10px">${esc(o.t)}</h4>
- <p style="color:var(--text-3);font-size:0.78rem;margin-bottom:8px"><strong style="color:var(--text-2)">来源信号:</strong> ${esc(o.signal)}</p>
- <p style="color:var(--text-2);font-size:0.88rem;line-height:1.6">${esc(o.action)}</p>
- </div>`;
- }).join('')}
- </div>
- <p class="sub" style="margin-top:32px">完整 ${OPPORTUNITIES.length} 个新机会按 5 大象限分独立章节深度展开,见下方 Section 06.A ~ 06.E。</p>
- <div class="toc" style="margin-top:24px">
- <a href="#sec-6a" style="border-color:var(--amber);color:var(--amber)">06.A 产品卖点 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('A')).length})</a>
- <a href="#sec-6b" style="border-color:var(--green);color:var(--green)">06.B 内容形态 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('B')).length})</a>
- <a href="#sec-6c" style="border-color:var(--purple);color:var(--purple)">06.C 人群渠道 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('C')).length})</a>
- <a href="#sec-6d" style="border-color:var(--blue);color:var(--blue)">06.D 投放机制 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('D')).length})</a>
- <a href="#sec-6e" style="border-color:var(--rose);color:var(--rose)">06.E 数据机制 (${OPPORTUNITIES.filter((o)=>o.cat.startsWith('E')).length})</a>
- </div>
- <h3 class="h2" style="margin-top:48px">方法论 — 4 条挖掘原则</h3>
- <div class="grid grid-4">
- <div class="card"><div class="tag">原则 1</div><h4 style="margin:10px 0">小样本不影响信号方向</h4><p style="color:var(--text-2);font-size:0.84rem">1 条专业参数评论 = 1 个产品价值锚点,<strong>信号密度</strong> > 统计显著性</p></div>
- <div class="card"><div class="tag green">原则 2</div><h4 style="margin:10px 0">每条评论都是潜在购买者</h4><p style="color:var(--text-2);font-size:0.84rem">不是数据,是真人,值得<strong>逐字解读</strong> — 词序、表情、IP 全有意义</p></div>
- <div class="card"><div class="tag purple">原则 3</div><h4 style="margin:10px 0">反直觉信号 > 平均值</h4><p style="color:var(--text-2);font-size:0.84rem">"泛流量型"互动最低却产生最高质量对话 — 这就是被低估的机会</p></div>
- <div class="card"><div class="tag rose">原则 4</div><h4 style="margin:10px 0">缺席与出现同等重要</h4><p style="color:var(--text-2);font-size:0.84rem">一线 IP 缺席、男性 KOC 缺席、品牌词命中 0 — <strong>"没有"才是最大的机会</strong></p></div>
- </div>
- </div>
- </section>
- ${(() => {
- const QUADRANTS = [
- { letter: 'A', cat: 'A · 产品卖点', color: 'amber', tagClass: '', accent: 'card-accent', desc: '从用户评论里反推的产品/卖点级机会 — 把"用户已经说出口"的需求变成可执行的内容指引/SKU/卖点。' },
- { letter: 'B', cat: 'B · 内容形态', color: 'green', tagClass: 'green', accent: 'card-green', desc: '内容打法升级 — 同样的预算,如何把"被低估的内容形态"翻转成主战场。' },
- { letter: 'C', cat: 'C · 人群渠道', color: 'purple', tagClass: 'purple', accent: '', desc: '人群和渠道的二八优化 — 让每一分预算都投在"会真买跑步机"的人身上,而不是看了不下单的远方观众。' },
- { letter: 'D', cat: 'D · 投放机制', color: 'blue', tagClass: 'blue', accent: 'card-blue', desc: '投放过程的机制化 — 把"凭感觉发笔记"变成"算法驱动止损/加投/预警",每轮都比上轮更聪明。' },
- { letter: 'E', cat: 'E · 数据机制', color: 'rose', tagClass: 'rose', accent: 'card-rose', desc: '长效数据资产 — 投后快照、博主行为预警,这是可以持续复用 N 轮投放的底层基建。' },
- ];
- return QUADRANTS.map((q) => {
- const list = OPPORTUNITIES.filter((o) => o.cat === q.cat);
- return `
- <!-- ============= 6.${q.letter} ${q.cat} ============= -->
- <section id="sec-6${q.letter.toLowerCase()}" data-num="06.${q.letter} / ${q.cat.split('·')[1].trim()}" style="justify-content:flex-start">
- <div class="inner">
- <div class="eyebrow" style="color:var(--${q.color})">Section 06.${q.letter} · ${q.cat}</div>
- <h2 class="h1" style="color:var(--${q.color})">${esc(q.cat)} <span style="color:var(--text-3);font-size:0.5em;font-weight:500">${list.length} 个新机会</span></h2>
- <p class="sub">${esc(q.desc)}</p>
- <div class="grid" style="gap:28px;margin-top:32px">
- ${list.map((o) => `
- <div class="card ${q.accent}" style="position:relative">
- <div style="position:absolute;top:18px;right:24px;font-family:var(--font-mono);font-size:2.4rem;font-weight:800;color:var(--${q.color});opacity:0.15;line-height:1">${o.id}</div>
- <div style="display:flex;gap:10px;align-items:center;margin-bottom:14px;flex-wrap:wrap">
- <span class="tag ${q.tagClass}" style="font-family:var(--font-mono);font-size:0.8rem">${o.id}</span>
- <span class="tag ${o.p === 'P0' ? 'rose' : o.p === 'P1' ? '' : 'purple'}">${o.p}</span>
- <h3 style="font-family:var(--font-head);font-size:1.4rem;font-weight:700;letter-spacing:-0.01em">${esc(o.t)}</h3>
- </div>
- <div class="grid grid-3" style="gap:18px;margin-top:18px">
- <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
- <div class="metric-label" style="margin-bottom:8px">📍 信号 / Signal</div>
- <p style="color:var(--text-2);font-size:0.88rem;line-height:1.65">${esc(o.signal)}</p>
- </div>
- <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
- <div class="metric-label" style="margin-bottom:8px">🎯 行动 / Action</div>
- <p style="color:var(--text-1);font-size:0.88rem;line-height:1.65;font-weight:500">${esc(o.action)}</p>
- </div>
- <div style="background:var(--bg-0);border-radius:8px;padding:18px;border-left:2px solid var(--${q.color})">
- <div class="metric-label" style="margin-bottom:8px">📈 预期 / Outcome</div>
- <p style="color:var(--text-2);font-size:0.88rem;line-height:1.65">${esc(o.outcome || '-')}</p>
- </div>
- </div>
- <div style="margin-top:22px;padding:20px;background:var(--bg-0);border-radius:8px">
- <div class="metric-label" style="margin-bottom:10px">💡 为什么要做 / Why</div>
- <p style="color:var(--text-2);font-size:0.92rem;line-height:1.75">${esc(o.why || '-')}</p>
- </div>
- ${Array.isArray(o.how) && o.how.length ? `
- <div style="margin-top:18px;padding:20px;background:var(--bg-0);border-radius:8px">
- <div class="metric-label" style="margin-bottom:12px">🛠️ 如何执行 / How (${o.how.length} 步)</div>
- <ol style="margin:0;padding-left:24px;color:var(--text-2);font-size:0.9rem;line-height:1.85">
- ${o.how.map((step) => `<li style="margin-bottom:6px">${esc(step)}</li>`).join('')}
- </ol>
- </div>
- ` : ''}
- </div>
- `).join('')}
- </div>
- </div>
- </section>`;
- }).join('');
- })()}
- <!-- ============= 页脚 ============= -->
- <section style="min-height:auto;padding:60px 24px;background:var(--bg-1)" data-num="END">
- <div class="inner" style="text-align:center">
- <p class="text-sm text-3">舒华跑步机 · 四月小红书 KOC 宣发结案报告 · 基于 ${summary.totalKocs} 位 KOC + ${allComments.length} 条评论真实数据生成</p>
- <p class="text-xs text-3 mono" style="margin-top:8px">Generated ${new Date().toISOString().slice(0,19).replace('T',' ')}</p>
- </div>
- </section>
- </main>
- <script>
- const TYPE_DATA = ${JSON.stringify(typeStats)};
- const TOPIC_DATA = ${JSON.stringify(TOPICS.map(t=>({tag:t.tag, color:t.color, count:topicHits[t.tag].length})))};
- const CLOUD_BRAND = ${JSON.stringify(cloudBrand)};
- const CLOUD_ACTIVITY = ${JSON.stringify(cloudActivity)};
- const CLOUD_CATEGORY = ${JSON.stringify(cloudCategory)};
- const CLOUD_COMMENTS = ${JSON.stringify(wordcloudComments.map(([n,v])=>({name:n,value:v})))};
- const COMMON = {
- backgroundColor: 'transparent',
- textStyle: { fontFamily: 'Inter, Noto Sans SC, system-ui', color: '#A8A8A8' }
- };
- function initWhenReady(){
- if (!window.echarts) { setTimeout(initWhenReady, 200); return; }
- // 内容形态 - 互动堆叠
- echarts.init(document.getElementById('chart-type-engagement')).setOption({
- ...COMMON,
- title: { text: '内容形态 · 总互动 / 篇数', left: 0, textStyle: { color:'#F5F5F5', fontSize:14, fontWeight:600 } },
- tooltip: { trigger:'axis' },
- legend: { textStyle:{color:'#A8A8A8'}, top: 0, right: 0 },
- grid: { left: 60, right: 30, bottom: 50, top: 60 },
- xAxis: { type:'category', data: TYPE_DATA.map(d=>d.type), axisLabel:{ color:'#A8A8A8', interval:0, rotate:15 }, axisLine:{ lineStyle:{ color:'rgba(255,255,255,0.1)'}} },
- yAxis: [
- { type:'value', name:'总互动', axisLabel:{color:'#A8A8A8'}, splitLine:{ lineStyle:{ color:'rgba(255,255,255,0.05)'}}, nameTextStyle:{color:'#A8A8A8'} },
- { type:'value', name:'篇数', axisLabel:{color:'#A8A8A8'}, splitLine:{show:false}, nameTextStyle:{color:'#A8A8A8'} }
- ],
- series: [
- { name:'总互动', type:'bar', data: TYPE_DATA.map(d=>d.engagement), itemStyle:{color:'#F5A623', borderRadius:[4,4,0,0]} },
- { name:'篇数', type:'line', yAxisIndex:1, data: TYPE_DATA.map(d=>d.count), itemStyle:{color:'#00DC82'}, lineStyle:{width:2}, smooth:true }
- ]
- });
- // 内容形态 - 互动率
- echarts.init(document.getElementById('chart-type-rate')).setOption({
- ...COMMON,
- title: { text: '内容形态 · 互动率 (%)', left: 0, textStyle: { color:'#F5F5F5', fontSize:14, fontWeight:600 } },
- tooltip: { trigger:'axis', formatter: (p)=> p[0].name+'<br/>'+p[0].value.toFixed(2)+'%' },
- grid: { left: 60, right: 30, bottom: 50, top: 60 },
- xAxis: { type:'category', data: TYPE_DATA.map(d=>d.type), axisLabel:{color:'#A8A8A8', interval:0, rotate:15} },
- yAxis: { type:'value', axisLabel:{color:'#A8A8A8', formatter:'{value}%'}, splitLine:{lineStyle:{color:'rgba(255,255,255,0.05)'}} },
- series: [{ type:'bar', data: TYPE_DATA.map(d=>+d.rate.toFixed(2)), itemStyle:{color:'#8B5CF6', borderRadius:[4,4,0,0]} }]
- });
- // 主题分布
- echarts.init(document.getElementById('chart-topics')).setOption({
- ...COMMON,
- title: { text: '评论主题命中分布', left: 0, textStyle: { color:'#F5F5F5', fontSize:14, fontWeight:600 } },
- tooltip: { trigger:'axis' },
- grid: { left: 140, right: 40, bottom: 30, top: 50 },
- xAxis: { type:'value', axisLabel:{color:'#A8A8A8'}, splitLine:{lineStyle:{color:'rgba(255,255,255,0.05)'}} },
- yAxis: { type:'category', data: TOPIC_DATA.map(d=>d.tag), axisLabel:{color:'#A8A8A8', fontSize:12} },
- series: [{
- type:'bar', data: TOPIC_DATA.map(d=>({value:d.count, itemStyle:{color:d.color, borderRadius:[0,4,4,0]}})),
- label:{show:true, position:'right', color:'#F5F5F5', fontSize:12}
- }]
- });
- function wordcloud(id, data, colors){
- if (!echarts.registerLayout && !echarts.WordCloud && !window['echarts-wordcloud']) {/* plugin loaded as side effect */}
- echarts.init(document.getElementById(id)).setOption({
- ...COMMON,
- tooltip: { show: true, formatter: (p)=> p.name + ' · ' + p.value },
- series: [{
- type: 'wordCloud',
- shape: 'circle',
- sizeRange: [12, 56],
- rotationRange: [-30, 30],
- rotationStep: 30,
- gridSize: 8,
- drawOutOfBound: false,
- layoutAnimation: true,
- textStyle: {
- fontFamily: 'Noto Sans SC, Inter, sans-serif',
- fontWeight: 600,
- color: () => colors[Math.floor(Math.random()*colors.length)]
- },
- emphasis: { textStyle: { color: '#F5A623', shadowBlur: 10, shadowColor: 'rgba(245,166,35,0.5)' } },
- data: data
- }]
- });
- }
- wordcloud('cloud-brand', CLOUD_BRAND, ['#F5A623','#FFB849','#FFC97D']);
- wordcloud('cloud-activity', CLOUD_ACTIVITY, ['#00DC82','#34E899','#5EEAB1']);
- wordcloud('cloud-category', CLOUD_CATEGORY, ['#3B82F6','#60A5FA','#93C5FD']);
- wordcloud('cloud-comments', CLOUD_COMMENTS, ['#FF4D8D','#FF7AAB','#FFA3C2','#A8A8A8']);
- }
- initWhenReady();
- </script>
- </body>
- </html>`;
- fs.writeFileSync(OUT_HTML, HTML, 'utf8');
- console.log('✓ HTML:', OUT_HTML, Math.round(HTML.length/1024)+'KB');
- // ============== 7. 渲染 MD ==============
- const md = [];
- const M = (s) => md.push(s);
- M('# 舒华跑步机 · 四月小红书 KOC 宣发 结案报告');
- M('');
- M(`> **投放期间**: 2026-04 · **生成时间**: ${new Date().toISOString().slice(0,19).replace('T',' ')} `);
- M(`> **数据范围**: ${summary.totalKocs} 位 KOC + ${allComments.length} 条公开评论 (覆盖 ${summary.withRealComments}/${summary.totalKocs} 篇笔记)`);
- M('');
- M('---');
- M('');
- M('## 一、数据汇总');
- M('');
- M('| 指标 | 数值 | 备注 |');
- M('|---|---:|---|');
- M(`| 投放 KOC | ${summary.totalKocs} | 家居 ${catStats.find(c=>c.category==='家居')?.count||0} + 好物 ${catStats.find(c=>c.category==='好物')?.count||0} |`);
- M(`| 总预算 | ¥${fmt(summary.totalSpend)} | 单价均值 ¥${Math.round(summary.totalSpend/summary.totalKocs)} |`);
- M(`| 总曝光 | ${fmt(summary.totalImpressions)} | CPM ¥${summary.cpm.toFixed(2)} |`);
- M(`| 总阅读 | ${fmt(summary.totalReads)} | 阅读率 ${(summary.totalReads/Math.max(summary.totalImpressions,1)*100).toFixed(1)}% |`);
- M(`| 总互动 | ${fmt(summary.totalEngagement)} | CPE ¥${summary.cpe.toFixed(2)} |`);
- M(`| 点赞 / 收藏 / 评论 | ${fmt(summary.totalLikes)} / ${fmt(summary.totalCollects)} / ${fmt(summary.totalComments)} | 评论激发率偏低 |`);
- M(`| 整体互动率 | ${pct(summary.engagementRate)} | 行业基准 3-5% |`);
- M(`| 笔记解析成功 | ${summary.resolved}/${summary.totalKocs} | 短链失效 ${summary.failed} 个 |`);
- M(`| 真实评论抓取 | ${allComments.length} 条 (xlsx 报备 ${summary.totalComments}) | 噪声率 ${noiseRate.toFixed(1)}% |`);
- M('');
- M('### 内容形态产出对比');
- M('');
- M('| 内容形态 | 篇数 | 总阅读 | 总互动 | 平均互动 | 互动率 | 总投入 |');
- M('|---|---:|---:|---:|---:|---:|---:|');
- for (const t of typeStats) {
- M(`| ${t.type} | ${t.count} | ${fmt(t.reads)} | ${fmt(t.engagement)} | ${t.avgEng} | ${t.rate.toFixed(2)}% | ¥${fmt(t.spend)} |`);
- }
- M('');
- M('---');
- M('');
- M('## 二、数据明细 (全 ' + summary.totalKocs + ' 位 KOC)');
- M('');
- M('> 按总互动数降序排列');
- M('');
- M('| # | KOC | 类目 | 内容形态 | 粉丝 | 单价 | 曝光 | 阅读 | 点赞 | 收藏 | 评论 | 互动 | 笔记ID |');
- M('|---:|---|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---|');
- const detailSorted = [...items].sort((a,b)=>num(b.engagement)-num(a.engagement));
- for (let i = 0; i < detailSorted.length; i++) {
- const r = detailSorted[i];
- M(`| ${i+1} | ${r.name} | ${r.category||'-'} | ${r.contentType||'-'} | ${fmt(r.followers)} | ¥${fmt(r.priceTotal)} | ${fmt(r.impressions)} | ${fmt(r.reads)} | ${fmt(r.likes)} | ${fmt(r.collects)} | ${fmt(r.comments)} | ${fmt(r.engagement)} | ${r.noteId||'❌失效'} |`);
- }
- M('');
- M('---');
- M('');
- M('## 三、话题数据 — 评论 VOC 主题分布');
- M('');
- M(`基于 **${allComments.length}** 条真实评论 (含 ${noiseComments.length} 条互助互赞噪声 = ${noiseRate.toFixed(1)}%) 的规则化主题命中:`);
- M('');
- M('| 主题 | 命中 | 占比 | 典型样本 |');
- M('|---|---:|---:|---|');
- for (const t of TOPICS) {
- const hits = topicHits[t.tag];
- const sample = hits.sort((a,b)=>b.like-a.like)[0];
- const sampleText = sample ? `[${sample.koc}@${sample.ip||'-'}] ${sample.content.replace(/\n/g,' ').replace(/\|/g,'\\|').slice(0,80)}` : '-';
- M(`| ${t.tag} | ${hits.length} | ${(hits.length/Math.max(allComments.length,1)*100).toFixed(1)}% | ${sampleText} |`);
- }
- M('');
- M(`### 真实评论原声 Top ${topPicks.length} (产品强相关 · 多主题轮询)`);
- M('');
- for (const { topic, c } of topPicks) {
- M(`- **[${topic}]** \`${c.koc}@${c.ip||'-'}\`: ${c.content.replace(/\n/g,' ')}`);
- }
- M('');
- M('---');
- M('');
- M('## 四、品牌相关词存量');
- M('');
- M('### 4.1 品牌词');
- M('');
- M('| 词 | 评论命中 | 状态 |');
- M('|---|---:|---|');
- for (const w of cloudBrand) M(`| ${w.name} | ${w.value-5 > 0 ? w.value-5 : 0} | ${w.value > 5 ? '✓ 已渗透' : '○ 待沉淀'} |`);
- M('');
- M('### 4.2 活动相关词');
- M('');
- M('| 词 | 评论命中 | 状态 |');
- M('|---|---:|---|');
- for (const w of cloudActivity) M(`| ${w.name} | ${w.value-5 > 0 ? w.value-5 : 0} | ${w.value > 5 ? '✓ 已渗透' : '○ 待沉淀'} |`);
- M('');
- M('### 4.3 品类词占位');
- M('');
- M('| 词 | 评论命中 | 状态 |');
- M('|---|---:|---|');
- for (const w of cloudCategory) M(`| ${w.name} | ${w.value-5 > 0 ? w.value-5 : 0} | ${w.value > 5 ? '✓ 已渗透' : '○ 待沉淀'} |`);
- M('');
- M('### 4.4 评论高频词 Top 30');
- M('');
- M('| 词 | 频次 |');
- M('|---|---:|');
- for (const [w, v] of wordcloudComments.slice(0, 30)) M(`| ${w} | ${v} |`);
- M('');
- M('### 关键洞察');
- M('');
- M('- **⚠️ 品牌词渗透不足**: "舒华/SHUA" 在评论中出现频次极低,用户更多在谈论"易跑/麦瑞克"等竞品和"健身房/减肥"等通用品类话题');
- M('- **⚠️ 活动词记忆点散**: 没有形成统一可记忆的活动钩子,KOC 笔记 hook 太分散');
- M('- **✓ 品类词承载明确**: "跑步机"作为品类词在用户语境中清晰存在,应捆绑"静音/减震/折叠"3 大附属词形成差异化');
- M('');
- M('---');
- M('');
- M('## 五、本次宣发的优点 / 不足 / 后续建议');
- M('');
- M('### 5.1 ✓ 优点');
- M('');
- for (const p of PROS) {
- M(`**${p.title}**`);
- M('');
- M(p.text);
- M('');
- }
- M('### 5.2 ✗ 不足');
- M('');
- for (const c of CONS) {
- M(`**${c.title}**`);
- M('');
- M(c.text);
- M('');
- }
- M('### 5.3 → 后续投放建议');
- M('');
- M('| 优先级 | 行动 | 说明 |');
- M('|---|---|---|');
- for (const r of RECS) {
- M(`| **${r.p}** | ${r.t} | ${r.b} |`);
- }
- M('');
- M('### 5.4 下一轮预算建议分配');
- M('');
- M('| 模块 | 占比 | 说明 |');
- M('|---|---:|---|');
- M('| 头/腰部 KOL | 40% | 2~3 位垂类健身/减脂 KOL,粉丝 ≥ 10万,单篇深度内容 |');
- M('| 优质 KOC 矩阵 | 35% | 25~30 篇,粉丝 ≥ 3,000,2 种形态各 15 篇 |');
- M('| 薯条/聚光投流 | 20% | 追加 Top 互动笔记,放大长尾流量 |');
- M('| 评论区运营 + 数据 | 5% | SOP 话术 + 风险词预警 + 投后 24h 抓取 |');
- M('');
- M('---');
- M('');
- M(`*本结案报告基于 ${summary.totalKocs} 位 KOC 投放数据 + ${allComments.length} 条公开评论,通过可复用 VOC 工作流自动生成。配套交互式 HTML 报告: \`shuhua-closing-report.html\`*`);
- fs.writeFileSync(OUT_MD, md.join('\n'), 'utf8');
- console.log('✓ MD:', OUT_MD, md.length, 'lines');
|