mirror of
https://github.com/primedigitaltech/market-assistant.git
synced 2026-07-22 08:01:34 +08:00
feat(report): remove §5 competitor matrix table, keep per-group charts
Made-with: Cursor
This commit is contained in:
parent
a1d0fa6686
commit
c45ec66d4c
@ -3,7 +3,7 @@
|
||||
关键词 → 调用 ``jd_keyword_pipeline`` 全链路采集 → 生成 **标准化竞品分析报告**(Markdown)。
|
||||
|
||||
报告结构对齐常见竞品分析框架:研究范围与方法、执行摘要、**整体市场观察(列表可见度 proxy)**、
|
||||
市场与竞争结构、**按细分类目分组的竞品对比矩阵**、价格分析、产品与宣称、**按细分类目的消费者反馈与用户画像**、策略提示与附录;并明确数据边界。
|
||||
市场与竞争结构、**按细分类目分组的竞品结构(统计图 + 合并表外置)**、价格分析、产品与宣称、**按细分类目的消费者反馈与用户画像**、策略提示与附录;并明确数据边界。
|
||||
若运行配置中提供了外部市场规模摘录(``EXTERNAL_MARKET_TABLE_ROWS``),则追加对应表格小节;否则不输出占位行。
|
||||
|
||||
依赖:全量抓取时与 ``jd_keyword_pipeline.py`` 相同(Node、h5st、Playwright、``common/jd_cookie.txt``)。
|
||||
@ -1655,7 +1655,7 @@ def _lines_4_reading_category(
|
||||
"",
|
||||
f"- 列表侧可读类目/简称共 **{len(cm_structure)}** 种取值,合计 **{total}** 行;"
|
||||
f"其中「{_md_cell(top_lbl, 40)}」行数最多,约占 **{100 * share:.1f}%**。",
|
||||
"- 若头部类目占比极高,说明当前关键词下货架被少数品类定义;跨品类机会需结合商详矩阵(§5)再核对。",
|
||||
"- 若头部类目占比极高,说明当前关键词下货架被少数品类定义;跨品类机会需结合 §5 细类结构与合并表再核对。",
|
||||
"",
|
||||
"| 类目/简称(Top 5) | 列表行数 | 占本章结构样本 |",
|
||||
"| --- | ---: | ---: |",
|
||||
@ -1800,7 +1800,7 @@ def build_competitor_markdown(
|
||||
"- **用途/场景**:对每条评价独立判断是否命中预设场景词;一条可计入多个场景,统计的是「提及该场景的评价条数」而非用户数。",
|
||||
"- **用户画像(第八章)**:正负面粗判含**口语短语**级摘录;关注词与场景**仅按细类**以条形图展示(场景图为**占该细类有效文本比例 %**);见 §8.3~8.4。",
|
||||
"- **各章衔接(可选)**:若任务配置 ``llm_section_bridges``(或部署侧环境变量启用),则在「## 一」至「## 九」各章二级标题后插入大模型撰写的**衔接分析**段落,便于阅读过渡;**定量结论仍以正文表格与摘要 JSON 为准**。",
|
||||
"- **细类大模型归纳(可选)**:若任务配置 ``llm_matrix_group_summaries`` / ``llm_price_group_summaries`` / ``llm_comment_group_summaries``(或对应 ``MA_ENABLE_LLM_*`` 环境变量),则在 **§5.1、§6.2、§8.6** 分别插入卖点/价盘/评论关注词的细类归纳;**仍以同章表格与 CSV 为准**。",
|
||||
"- **细类大模型归纳(可选)**:若任务配置 ``llm_price_group_summaries`` / ``llm_comment_group_summaries``(或对应 ``MA_ENABLE_LLM_*`` 环境变量),则在 **§6.2、§8.6** 插入价盘/评论关注词的细类归纳;**§5 不再输出矩阵表**,卖点/配料等仍以 ``keyword_pipeline_merged.csv`` 与 JSON 为准。",
|
||||
"- **检索结果规模**:来自京东 PC 搜索返回的「结果条数」类指标,表示平台侧申报的匹配数量级,**不等于**动销、库存或独立 SKU 数。",
|
||||
"",
|
||||
"### 1.4 主要局限",
|
||||
@ -1863,7 +1863,7 @@ def build_competitor_markdown(
|
||||
)
|
||||
elif list_export and cr1_deep is not None and top_brand_deep and not brands_s:
|
||||
exec_bullets.append(
|
||||
f"列表导出缺少品牌标题字段,**深入 {n_sku} SKU** 商详品牌第一大品牌份额 ≈ **{100 * cr1_deep:.1f}%**(「{top_brand_deep}」),供与 §5 矩阵对照。"
|
||||
f"列表导出缺少品牌标题字段,**深入 {n_sku} SKU** 商详品牌第一大品牌份额 ≈ **{100 * cr1_deep:.1f}%**(「{top_brand_deep}」),供与 §5 细类结构对照。"
|
||||
)
|
||||
if pst:
|
||||
price_src_short = (
|
||||
@ -2053,7 +2053,7 @@ def build_competitor_markdown(
|
||||
lines.append(
|
||||
f"*列表导出中店铺/品牌标题有效 **{brand_rows_n}** 条,"
|
||||
f"低于建议阈值(≥{min_brand_rows}),品牌集中度未展开。**店铺结构见 §4.2**;"
|
||||
f"商详品牌在 **§5**。*"
|
||||
f"商详品牌在 **§5 细类结构**。*"
|
||||
)
|
||||
else:
|
||||
lines.append("*深入子样本无可用品牌字段。*")
|
||||
@ -2116,24 +2116,17 @@ def build_competitor_markdown(
|
||||
[
|
||||
"---",
|
||||
"",
|
||||
"## 五、竞品对比矩阵(按细分类目分组)",
|
||||
"## 五、竞品结构(按细分类目分组)",
|
||||
"",
|
||||
"优先按商详**类目路径**列分组:**三级路径**取中间一段(如 … > **饼干** > 粗粮饼干),"
|
||||
"**四级及以上**取倒数第二段(如 … > **面条** > 挂面)。若该列为空,退化为搜索列表中的类目或规格属性;仍无则「未归类」。全量合并模式下另有更多商详字段可供核对。",
|
||||
"SKU 依商详**类目路径**聚合为细类:**三级路径**取中间一段(如 … > **饼干** > 粗粮饼干),"
|
||||
"**四级及以上**取倒数第二段(如 … > **面条** > 挂面);类目列为空时退化为列表类目或规格,仍无则「未归类」。",
|
||||
"",
|
||||
"维度说明:**产品**(标题/规格)、**价格**(列表展示)、**渠道**(京东店铺)、**推广**(卖点/榜单文案)、"
|
||||
"**类目**、**配料表**(见下)、**声量**(评价量与摘要)。",
|
||||
"",
|
||||
"**配料表**:优先使用配料正文列(开启配料视觉解析时为识别出的文字);"
|
||||
"仅有详情长图链接时列内会提示;若商详参数含「配料/配料表:」则摘录该段。"
|
||||
"均为页面信息摘录,**以包装实物与法规标签为准**。",
|
||||
"**本版不再在正文打印细类矩阵表**(宽表影响阅读);各 SKU 的标题、品牌、店铺、标价/详情价、卖点、配料、评价量与摘要等,"
|
||||
"请直接查看本批次目录下 ``keyword_pipeline_merged.csv``,或调用 API 结构化字段 ``matrix_by_group``。",
|
||||
"下列按细类给出 **SKU 款数** 及 **展示价 / 评价量** 统计图(与合并表、``matrix_by_group`` 同源)。",
|
||||
"",
|
||||
]
|
||||
)
|
||||
matrix_header = [
|
||||
"| SKU | 产品(标题) | 品牌 | 标价 | 详情价 | 渠道(店铺) | 推广(卖点) | 榜单/标签 | 类目 | 配料表 | 评价量(搜索) | 消费者反馈摘要 |",
|
||||
"| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |",
|
||||
]
|
||||
grouped_matrix = _merged_rows_grouped_for_matrix(merged_rows)
|
||||
if not grouped_matrix:
|
||||
lines.append("*无合并表 SKU。*")
|
||||
@ -2141,39 +2134,20 @@ def build_competitor_markdown(
|
||||
for gi, (gname, grows) in enumerate(grouped_matrix):
|
||||
lines.append(f"### {gname}(**{len(grows)}** 款)")
|
||||
lines.append("")
|
||||
lines.extend(matrix_header)
|
||||
grows_sorted = sorted(grows, key=lambda r: _cell(r, sku_header) or "")
|
||||
for row in grows_sorted:
|
||||
lines.append(
|
||||
_competitor_matrix_md_line(
|
||||
row, sku_header=sku_header, title_h=title_h
|
||||
)
|
||||
)
|
||||
lines.append(
|
||||
"*SKU 级字段明细见 ``keyword_pipeline_merged.csv``(本细类 SKU 与上节分组规则一致)。*"
|
||||
)
|
||||
lines.append("")
|
||||
slug_mx = _scenario_group_asset_slug(gname, gi)
|
||||
lines.extend(
|
||||
_embed_chart(
|
||||
run_dir,
|
||||
f"chart_matrix_prices_reviews__{slug_mx}.png",
|
||||
f"「{_md_cell(gname, 24)}」细类 · **展示价与评价量**(条形图;与上表同源:"
|
||||
f"「{_md_cell(gname, 24)}」细类 · **展示价与评价量**(条形图;与合并表及 ``matrix_by_group`` 同源:"
|
||||
f"价取 detail_price_final→标价→券后 优先可解析数值;评价量为搜索侧「评价量」字段摘录)",
|
||||
)
|
||||
)
|
||||
|
||||
_mx_llm = (llm_matrix_section_md or "").strip()
|
||||
if _mx_llm:
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
"### 5.1 细类要点归纳(大模型)",
|
||||
"",
|
||||
"> **说明**:模型按 §5 同细类拆分,仅基于上表矩阵摘录(标题/卖点/配料等)与每细类 ``price_stats``(与 §6 分位数同源对象)归纳;**不含**医学或功效结论。配料与宣称以页面为准。",
|
||||
"",
|
||||
_mx_llm,
|
||||
"",
|
||||
]
|
||||
)
|
||||
|
||||
ch6_price_title = (
|
||||
"## 六、价格分析(PC 搜索列表全量)"
|
||||
if list_export and pst_list.get("n", 0) > 0
|
||||
@ -2237,7 +2211,7 @@ def build_competitor_markdown(
|
||||
"### 6.2 细类价盘要点归纳(大模型)",
|
||||
"",
|
||||
"> **说明**:以下为模型按 §5 同细类拆分、仅基于上文本节价统计与价字段摘录的归纳(价带与价差);"
|
||||
"不含配料/宣称/场景关键词分析——见 §5「细类要点归纳(大模型)」。具体数值仍以正文表格及批次 CSV 为准。",
|
||||
"不含配料/宣称/场景关键词分析。具体数值仍以 **§6** 表格及 ``keyword_pipeline_merged.csv`` 为准。",
|
||||
"",
|
||||
_pr_llm,
|
||||
"",
|
||||
@ -2265,7 +2239,7 @@ def build_competitor_markdown(
|
||||
"",
|
||||
"### 8.1 方法",
|
||||
"",
|
||||
"- **细类划分**:与 **§5 竞品矩阵** 相同,依据商详类目路径解析为「饼干 / 西式糕点 / …」等(规则见 §5 章首说明)。",
|
||||
"- **细类划分**:与 **§5** 相同的商详类目路径规则(见 §5 章首)。",
|
||||
"- **归因**:每条评价按其 SKU 对应到深入样本,再映射到该 SKU 所属细类;SKU 不在合并表中的评价单独归入说明性分组。",
|
||||
"- **正负面粗判(§8.2)**:先以关键词规则与图表做粗分;若任务开启 **llm_comment_sentiment**,可附**大模型对抽样原文的主题归因**(尤其负向「用户在抱怨什么」),与词频条形图互补。",
|
||||
"- **关注词按细类(§8.3)**:对组内评价正文做子串计数并出条形图;若无逐条正文则用该细类下评价摘要列拼接兜底;与配置关注词及联想扩展同源。",
|
||||
|
||||
@ -431,24 +431,8 @@ def write_competitor_analysis_for_run_dir(
|
||||
)
|
||||
|
||||
if want_mx and not skip_mx and merged_rows:
|
||||
pl_mx = jcr.build_matrix_groups_llm_payload(
|
||||
merged_rows, sku_header=sku_h, title_h=title_h
|
||||
)
|
||||
if pl_mx:
|
||||
matrix_llm_rec["attempted"] = True
|
||||
try:
|
||||
from .llm_generate import generate_matrix_group_summaries_llm
|
||||
|
||||
llm_matrix_md = generate_matrix_group_summaries_llm(
|
||||
pl_mx, keyword=kw
|
||||
)
|
||||
matrix_llm_rec["ok"] = True
|
||||
matrix_llm_rec["chars"] = len(llm_matrix_md)
|
||||
except Exception as e:
|
||||
matrix_llm_rec["ok"] = False
|
||||
matrix_llm_rec["error"] = str(e)
|
||||
else:
|
||||
matrix_llm_rec["skipped"] = "empty_matrix_payload"
|
||||
# §5 正文已取消细类矩阵表,不再向报告嵌入矩阵要点 LLM 段落。
|
||||
matrix_llm_rec["skipped"] = "matrix_table_removed_from_report"
|
||||
elif skip_mx:
|
||||
matrix_llm_rec["skipped"] = "MA_SKIP_LLM_MATRIX_GROUP_SUMMARIES"
|
||||
elif not want_mx:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user