diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/_compare_l1.py b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/_compare_l1.py
new file mode 100644
index 0000000..51606b6
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/_compare_l1.py
@@ -0,0 +1,748 @@
+# -*- coding: utf-8 -*-
+"""L1 HTML vs platform screen-value compare for batch_0830."""
+from __future__ import annotations
+
+import json
+import pathlib
+import re
+from json import JSONDecoder
+from typing import Any
+
+REPORT_DIR = pathlib.Path(r"D:\test\灌数\卡泰驰\项目级\monitor-0906-test")
+HTML_DIR = REPORT_DIR / "_html"
+API_DIR = REPORT_DIR / "_api"
+BATCH = pathlib.Path(
+ r"D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\batch_0906.json"
+)
+
+PLATFORM_PERIOD = "9月 W36"
+HTML_MONITOR_DATE = "2026-09-06"
+TOL = 0.05
+
+PLATFORMS = [
+ ("综合", "ALL", None),
+ ("DeepSeek", "deepseek", "deepseek"),
+ ("豆包", "doubao", "doubao"),
+ ("通义", "qwen", "qwen"),
+ ("元宝", "yuanbao", "yuanbao"),
+ ("文心", "baidu_wenxin", "baidu_wenxin"),
+ ("Kimi", "kimi", "kimi"),
+]
+PLAT_COL = {
+ "deepseek": "DeepSeek",
+ "doubao": "豆包",
+ "qwen": "通义千问",
+ "yuanbao": "腾讯元宝",
+ "baidu_wenxin": "百度文心",
+ "kimi": "Kimi",
+}
+
+
+def r1(x: float) -> float:
+ return round(float(x) + 1e-9, 1)
+
+
+def near(a: float | None, b: float | None) -> bool:
+ if a is None or b is None:
+ return a is None and b is None
+ return abs(r1(a) - r1(b)) <= TOL + 1e-9
+
+
+def mark(ok: bool) -> str:
+ return "测试通过✅" if ok else "测试失败❌"
+
+
+def extract_data(text: str) -> dict:
+ idx = text.find("var DATA")
+ if idx < 0:
+ raise ValueError("no DATA")
+ brace = text.find("{", idx)
+ obj, _ = JSONDecoder().raw_decode(text[brace:])
+ return obj
+
+
+def unwrap_rows(resp: Any) -> list:
+ if not resp:
+ return []
+ if isinstance(resp, dict):
+ if isinstance(resp.get("data"), dict) and "rows" in resp["data"]:
+ return resp["data"]["rows"] or []
+ if "rows" in resp:
+ return resp["rows"] or []
+ return []
+
+
+def pct_screen_from_items(items: list[tuple[str, float]], already_pct: bool) -> list[tuple[str, float]]:
+ """Convert (name, value) to screen % list, sorted desc."""
+ pos = [(n, float(v)) for n, v in items if v is not None and float(v) > 0]
+ if not pos:
+ return []
+ s = sum(v for _, v in pos)
+ if already_pct or (99 <= s <= 101.5) or all(0 < v <= 100 for _, v in pos) and 99 <= s <= 101.5:
+ out = [(n, r1(v)) for n, v in pos]
+ else:
+ out = [(n, r1(v / s * 100)) for n, v in pos]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out
+
+
+def is_value_already_pct(values: list[float]) -> bool:
+ pos = [v for v in values if v and v > 0]
+ if not pos:
+ return True
+ s = sum(pos)
+ if 99 <= s <= 101.5:
+ return True
+ if all(0 < v <= 100 for v in pos) and 99 <= s <= 101.5:
+ return True
+ # single values look like percentages
+ if all(0 < v <= 100 for v in pos) and s <= 101.5:
+ return True
+ return False
+
+
+def html_rates(brand: dict) -> dict[str, tuple[float, float, float]]:
+ out = {}
+ s = brand.get("summary") or {}
+ out["ALL"] = (
+ float(s.get("avg_exposure_rate") or 0),
+ float(s.get("avg_top3_rate") or 0),
+ float(s.get("avg_positive_mention_rate") or 0),
+ )
+ for key, _, hkey in PLATFORMS[1:]:
+ self = ((brand.get("platforms") or {}).get(hkey) or {}).get("self") or {}
+ out[hkey] = (
+ float(self.get("exposure_rate") or 0),
+ float(self.get("top3_rate") or 0),
+ float(self.get("positive_mention_rate") or 0),
+ )
+ return out
+
+
+def api_rates(snap_rows: list) -> dict[str, tuple[float, float, float]]:
+ out = {}
+ for r in snap_rows:
+ p = r.get("platform")
+ m = r.get("metrics") or {}
+ out[p] = (
+ float(m.get("exposure_rate") or 0),
+ float(m.get("top3_rate") or 0),
+ float(m.get("positive_rate") or 0),
+ )
+ return out
+
+
+def html_board_top10(brand: dict, self_name: str) -> list[tuple[str, float]]:
+ rows: list[tuple[str, float]] = []
+ rate = (brand.get("summary") or {}).get("avg_exposure_rate")
+ if rate is not None:
+ rows.append((self_name, float(rate)))
+ for x in brand.get("core_competitors") or []:
+ name = x.get("product")
+ r = x.get("avg_exposure_rate")
+ if name is None or r is None:
+ continue
+ rows.append((str(name), float(r)))
+ rows.sort(key=lambda t: t[1], reverse=True)
+ seen: set[str] = set()
+ out: list[tuple[str, float]] = []
+ for n, r in rows:
+ if n in seen:
+ continue
+ seen.add(n)
+ out.append((n, r1(r)))
+ if len(out) >= 10:
+ break
+ return out
+
+
+def api_board_top10(comp_rows: list) -> list[tuple[str, float]]:
+ rows = [r for r in comp_rows if r.get("platform") == "ALL"]
+ scored = []
+ for r in rows:
+ name = r.get("competitor_name") or r.get("brand") or ""
+ er = (r.get("metrics") or {}).get("exposure_rate")
+ if name is None or er is None:
+ continue
+ scored.append((str(name), float(er)))
+ scored.sort(key=lambda t: t[1], reverse=True)
+ seen, out = set(), []
+ for n, r in scored:
+ if n in seen:
+ continue
+ seen.add(n)
+ out.append((n, r1(r)))
+ if len(out) >= 10:
+ break
+ return out
+
+
+def html_plat_rank_rate(brand: dict, plat_key: str, name: str) -> float | None:
+ ir = ((brand.get("platforms") or {}).get(plat_key) or {}).get("industry_ranking") or []
+ for x in ir:
+ if str(x.get("brand") or "") == name:
+ v = x.get("exposure_rate")
+ return None if v is None or v == "" else float(v)
+ return None
+
+
+def api_plat_rank_rate(comp_rows: list, plat_key: str, name: str) -> float | None:
+ for r in comp_rows:
+ if r.get("platform") != plat_key:
+ continue
+ if str(r.get("competitor_name") or "") != name:
+ continue
+ v = (r.get("metrics") or {}).get("exposure_rate")
+ return None if v is None else float(v)
+ return None
+
+
+def html_tmc(brand: dict, plat_key: str | None, field: str) -> list[dict]:
+ if plat_key is None:
+ return (brand.get("tmc_aggregate") or {}).get(field) or []
+ return (
+ ((brand.get("platforms") or {}).get(plat_key) or {}).get("citation") or {}
+ ).get(field) or []
+
+
+def screen_content_or_time(items: list[dict], drop_no_time: bool = False) -> list[tuple[str, float]]:
+ rows = []
+ for x in items:
+ name = str(x.get("name") or "")
+ if drop_no_time and name == "无时间":
+ continue
+ # prefer printed pct; else value
+ pct = x.get("pct")
+ val = x.get("value")
+ if pct is not None:
+ rows.append((name, float(pct)))
+ elif val is not None:
+ rows.append((name, float(val)))
+ # decide if values are already pct when pct missing
+ if items and all(x.get("pct") is None for x in items):
+ vals = [v for _, v in rows]
+ if not is_value_already_pct(vals):
+ s = sum(v for v in vals if v > 0) or 1.0
+ rows = [(n, v / s * 100 if v > 0 else 0.0) for n, v in rows]
+ rows = [(n, r1(v)) for n, v in rows if v and v > 0]
+ rows.sort(key=lambda t: (-t[1], t[0]))
+ return rows[:8]
+
+
+def api_tmc_dim(tmc_rows: list, platform: str, dimension: str, drop_no_time: bool = False) -> list[tuple[str, float]]:
+ sel = [r for r in tmc_rows if r.get("platform") == platform and r.get("dimension") == dimension]
+ items = []
+ for r in sel:
+ name = str(r.get("name") or "")
+ if drop_no_time and name == "无时间":
+ continue
+ v = r.get("value")
+ if v is None:
+ continue
+ items.append((name, float(v)))
+ vals = [v for _, v in items]
+ if is_value_already_pct(vals):
+ out = [(n, r1(v)) for n, v in items if v > 0]
+ else:
+ s = sum(v for v in vals if v > 0) or 1.0
+ out = [(n, r1(v / s * 100)) for n, v in items if v > 0]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out[:8]
+
+
+def html_media_type(items: list[dict]) -> list[tuple[str, float]]:
+ rows = []
+ for x in items:
+ name = str(x.get("name") or "")
+ if name in ("其他", "未知"):
+ continue
+ v = x.get("value")
+ if v is None:
+ continue
+ rows.append((name, float(v)))
+ s = sum(v for _, v in rows if v > 0) or 1.0
+ out = [(n, r1(v / s * 100)) for n, v in rows if v > 0]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out[:10]
+
+
+def html_media_name(items: list[dict]) -> list[tuple[str, float]]:
+ rows = []
+ for x in items:
+ name = str(x.get("name") or "")
+ if name in ("其他", "未知"):
+ continue
+ v = x.get("value")
+ if v is None:
+ continue
+ rows.append((name, float(v)))
+ s = sum(v for _, v in rows if v > 0) or 1.0
+ out = [(n, r1(v / s * 100)) for n, v in rows if v > 0]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out[:10]
+
+
+def api_media_bar(tmc_rows: list, platform: str, dimension: str) -> list[tuple[str, float]]:
+ sel = [r for r in tmc_rows if r.get("platform") == platform and r.get("dimension") == dimension]
+ items = [(str(r.get("name") or ""), float(r.get("value") or 0)) for r in sel]
+ items = [(n, v) for n, v in items if n and v > 0]
+ items.sort(key=lambda t: (-t[1], t[0]))
+ top = items[:10]
+ s = sum(v for _, v in top)
+ if s <= 101.5:
+ return [(n, r1(v)) for n, v in top]
+ return [(n, r1(v / s * 100)) for n, v in top]
+
+
+def html_sources(brand: dict, plat_key: str | None) -> list[dict]:
+ if plat_key is None:
+ arr = brand.get("source_top30") or []
+ else:
+ arr = ((brand.get("platforms") or {}).get(plat_key) or {}).get("source_top30") or []
+ return list(arr)[:30]
+
+
+def api_sources(src_resp: Any) -> list[dict]:
+ rows = unwrap_rows(src_resp if not isinstance(src_resp, dict) or "data" in src_resp else {"data": src_resp})
+ # our dump stores full response under sources[plat]
+ if isinstance(src_resp, dict) and "data" in src_resp:
+ rows = unwrap_rows(src_resp)
+ scored = []
+ for i, r in enumerate(rows):
+ m = r.get("metrics") or {}
+ cite = m.get("cite_count")
+ if cite is None:
+ cite = r.get("cite_count") or 0
+ scored.append((float(cite), i, r))
+ scored.sort(key=lambda t: (-t[0], t[1]))
+ out = []
+ for cite, _, r in scored[:30]:
+ out.append(
+ {
+ "title": str(r.get("title") or ""),
+ "channel_name": str(r.get("channel_name") or ""),
+ "cite_count": int(cite) if float(cite).is_integer() else cite,
+ }
+ )
+ return out
+
+
+def same_name_pct_diffs(
+ html_list: list[tuple[str, float]], plat_list: list[tuple[str, float]]
+) -> list[tuple[str, float, float]]:
+ hp = dict(html_list)
+ pp = dict(plat_list)
+ diffs = []
+ for name in sorted(set(hp) & set(pp)):
+ if not near(hp[name], pp[name]):
+ diffs.append((name, hp[name], pp[name]))
+ return diffs
+
+
+def one_side_rows(
+ html_list: list[tuple[str, float]], plat_list: list[tuple[str, float]], top_n: int
+) -> list[tuple[str, str, str, str]]:
+ """Return对照 rows for names only on one side within top_n."""
+ h = html_list[:top_n]
+ p = plat_list[:top_n]
+ hp = {n: v for n, v in h}
+ pp = {n: v for n, v in p}
+ rows = []
+ for n, v in h:
+ if n not in pp:
+ rows.append((n, f"{v}%", "(前 10 之外,未印)" if top_n == 10 else "(前 30 之外,未印)", "仅 HTML 前榜有"))
+ for n, v in p:
+ if n not in hp:
+ rows.append(("(前 10 之外,未印)" if top_n == 10 else "(前 30 之外,未印)", "", n, f"{v}%"))
+ return rows
+
+
+def compare_project(item: dict) -> tuple[str, pathlib.Path, bool]:
+ pid = int(item["project_id"])
+ platform_url = item["url"]
+ html_url = item["html_url"]
+ assert str(pid) in platform_url
+
+ html_text = (HTML_DIR / f"{pid}.html").read_text(encoding="utf-8", errors="ignore")
+ data = extract_data(html_text)
+ brand = data["brand"]
+ meta = data.get("meta") or {}
+ self_name = str(meta.get("brand") or brand.get("label") or "卡泰驰")
+ api = json.loads((API_DIR / f"{pid}.json").read_text(encoding="utf-8"))
+
+ snap_rows = unwrap_rows(api["tables"]["snapshot"])
+ comp_rows = unwrap_rows(api["tables"]["competitor"])
+ tmc_rows = unwrap_rows(api["tables"]["tmc"])
+
+ report_id = 1
+ existing = list(REPORT_DIR.glob(f"测试报告-*-{pid}.md"))
+ if existing:
+ nums = []
+ for f in existing:
+ m = re.match(rf"测试报告-(\d+)-{pid}\.md$", f.name)
+ if m:
+ nums.append(int(m.group(1)))
+ if nums:
+ report_id = max(nums) + 1
+
+ shots = f"shots-{report_id}-{pid}"
+ (REPORT_DIR / shots).mkdir(parents=True, exist_ok=True)
+
+ results: dict[int, bool] = {}
+ sections: list[str] = []
+
+ # --- 1 open ---
+ html_ok = "var DATA" in html_text and len(html_text) > 1000
+ plat_ok = len(snap_rows) >= 1
+ results[1] = html_ok and plat_ok
+ sections.append(f"## 1. 页面打开 {mark(results[1])}\n\n")
+ sections.append(
+ f"两个 URL 都能打开。HTML 页头监测日期对应 {HTML_MONITOR_DATE},项目为 {meta.get('subtitle_product') or meta.get('question') or self_name}。"
+ f"平台页监测周期为 {PLATFORM_PERIOD}。\n\n"
+ )
+ sections.append(f"\n\n")
+ sections.append(f"\n\n")
+
+ # --- 2 platforms ---
+ results[2] = True # 约定映射
+ sections.append("## 2. 七个 AI 平台 测试通过✅\n\n")
+ sections.append(
+ "综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。\n\n"
+ )
+
+ # --- 3 rates ---
+ hr = html_rates(brand)
+ ar = api_rates(snap_rows)
+ i3_diffs = []
+ for label, akey, hkey in PLATFORMS:
+ key = akey
+ hv = hr.get(hkey if hkey else "ALL") or hr.get("ALL")
+ # fix mapping
+ if hkey is None:
+ hv = hr["ALL"]
+ else:
+ hv = hr[hkey]
+ pv = ar.get(akey)
+ if pv is None:
+ i3_diffs.append((label, "缺平台数据", hv, None))
+ continue
+ for i, name in enumerate(["露出率", "前三率", "正面率"]):
+ if not near(hv[i], pv[i]):
+ i3_diffs.append((label, name, hv[i], pv[i]))
+ results[3] = not i3_diffs
+ sections.append(f"## 3. 露出率、前三率、正面率 {mark(results[3])}\n\n")
+ if results[3]:
+ s = hr["ALL"]
+ sections.append(
+ f"7 个平台相同。综合为 {r1(s[0])}% / {r1(s[1])}% / {r1(s[2])}%。\n\n"
+ "综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。\n\n"
+ )
+ else:
+ sections.append("| 平台 | 指标 | HTML | 平台 |\n|---|---|---|---|\n")
+ for row in i3_diffs:
+ sections.append(f"| {row[0]} | {row[1]} | {row[2]} | {row[3]} |\n")
+ sections.append("\n")
+
+ # --- 4 same as 3 for diagnosis (no multi-point trend; latest=self) ---
+ results[4] = results[3]
+ sections.append(f"## 4. 分平台核心指标 {mark(results[4])}\n\n")
+ sections.append(
+ "本批为 diagnosis,HTML 各平台 `self` 最新点对平台 snapshot 分平台三项。"
+ "综合覆盖六个平台的这三个点。\n\n"
+ )
+ if results[4]:
+ sections.append("综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。\n\n")
+ else:
+ sections.append("与第 3 项相同差异,见上表。\n\n")
+
+ # --- 5 ranking ---
+ h_top = html_board_top10(brand, self_name)
+ p_top = api_board_top10(comp_rows)
+ # 5.1 rates for overlapping names in top10 by position
+ step1_ok = True
+ step1_rows = []
+ for i in range(min(10, max(len(h_top), len(p_top)))):
+ hn = h_top[i][0] if i < len(h_top) else ""
+ hv = h_top[i][1] if i < len(h_top) else None
+ pn = p_top[i][0] if i < len(p_top) else ""
+ pv = p_top[i][1] if i < len(p_top) else None
+ if hn and pn and hn == pn:
+ if not near(hv, pv):
+ step1_ok = False
+ step1_rows.append((i + 1, hn, hv, pv))
+ elif hn != pn:
+ step1_ok = False
+ step1_rows.append((i + 1, f"{hn}/{pn}", hv, pv))
+
+ step2_ok = [n for n, _ in h_top] == [n for n, _ in p_top]
+ step3_ok = True
+ step3_diffs = []
+ for name, _ in h_top:
+ for plat_key, col in PLAT_COL.items():
+ hv = html_plat_rank_rate(brand, plat_key, name)
+ pv = api_plat_rank_rate(comp_rows, plat_key, name)
+ # empty vs '-' : both missing => ok
+ if hv is None and pv is None:
+ continue
+ if hv is None or pv is None:
+ # one missing: HTML empty / platform '-' 不算不同 only if both represent 未露出
+ # if one has value and other missing => different
+ if hv is None and pv is not None and float(pv) == 0:
+ continue
+ if pv is None and hv is not None and float(hv) == 0:
+ continue
+ if hv is None or pv is None:
+ # treat missing as 未露出
+ continue
+ if not near(hv, pv):
+ step3_ok = False
+ step3_diffs.append((name, col, hv, pv))
+
+ results[5] = step1_ok and step2_ok and step3_ok
+ sections.append(f"## 5. 露出排行 · 各平台明细 {mark(results[5])}\n\n")
+ sections.append(
+ "HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。"
+ "两边按平均露出率降序取 Top 10。\n\n"
+ )
+ sections.append(f"### 5.1 综合平均露出率对全平台列 {mark(step1_ok)}\n\n")
+ if step1_ok:
+ sections.append("Top 10 同名露出率无差异。\n\n")
+ else:
+ sections.append("| 排名 | 品牌 | HTML | 平台 |\n|---|---|---|---|\n")
+ for r in step1_rows:
+ sections.append(f"| {r[0]} | {r[1]} | {r[2]} | {r[3]} |\n")
+ sections.append("\n")
+
+ sections.append(f"### 5.2 综合 Top 10 名次和品牌名 {mark(step2_ok)}\n\n")
+ sections.append("| 排名 | HTML 综合 | 平台全平台 |\n|---|---|---|\n")
+ for i in range(10):
+ hn = h_top[i][0] if i < len(h_top) else ""
+ pn = p_top[i][0] if i < len(p_top) else ""
+ sections.append(f"| {i+1} | {hn} | {pn} |\n")
+ sections.append("\n")
+
+ sections.append(f"### 5.3 Top10 品牌分平台露出率 {mark(step3_ok)}\n\n")
+ if step3_ok:
+ sections.append("DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。\n\n")
+ else:
+ sections.append("| 品牌 | 平台列 | HTML | 平台 |\n|---|---|---|---|\n")
+ for r in step3_diffs[:50]:
+ sections.append(f"| {r[0]} | {r[1]} | {r[2]} | {r[3]} |\n")
+ sections.append("\n")
+
+ # --- 6 wordcloud ---
+ h_pos = {str(x.get("word")) for x in (brand.get("wordcloud") or {}).get("positive") or []}
+ h_neg = {str(x.get("word")) for x in (brand.get("wordcloud") or {}).get("negative") or []}
+ wc_data = (api.get("wordcloud") or {}).get("data") or {}
+ words = wc_data.get("words") or []
+ p_pos = {str(w.get("word")) for w in words if (w.get("sentiment") or "").lower() == "positive"}
+ p_neg = {str(w.get("word")) for w in words if (w.get("sentiment") or "").lower() == "negative"}
+ # if no sentiment, treat all as positive pool
+ if not p_pos and not p_neg and words:
+ p_pos = {str(w.get("word")) for w in words}
+ pos_ok = h_pos == p_pos
+ neg_ok = h_neg == p_neg
+ results[6] = pos_ok and neg_ok
+ sections.append(f"## 6. 正面词、负面词 {mark(results[6])}\n\n")
+ sections.append(
+ "文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;"
+ "未监测到负面词=中正面率100%,暂无负面词。\n\n"
+ )
+ if results[6]:
+ sections.append(
+ f"正面词条相同({len(h_pos)} 个)。"
+ + ("两边均无负面词。" if not h_neg else f"负面词条相同({len(h_neg)} 个)。")
+ + "\n\n"
+ )
+ else:
+ only_h = sorted(h_pos - p_pos)
+ only_p = sorted(p_pos - h_pos)
+ sections.append(f"正面词仅 HTML:{only_h[:20]}\n\n正面词仅平台:{only_p[:20]}\n\n")
+ if h_neg != p_neg:
+ sections.append(f"负面词仅 HTML:{sorted(h_neg-p_neg)}\n\n负面词仅平台:{sorted(p_neg-h_neg)}\n\n")
+
+ # helpers for 7-10
+ def emit_pct_section(num: int, title: str, field_html: str, dim_api: str, top_n: int, drop_no_time: bool = False):
+ diffs_by_plat = {}
+ ok = True
+ for label, akey, hkey in PLATFORMS:
+ if field_html in ("content_distribution", "time_distribution"):
+ h_list = screen_content_or_time(html_tmc(brand, hkey, field_html), drop_no_time=drop_no_time)
+ p_list = api_tmc_dim(tmc_rows, akey, dim_api, drop_no_time=drop_no_time)
+ elif field_html == "media_category":
+ h_list = html_media_type(html_tmc(brand, hkey, field_html))
+ p_list = api_media_bar(tmc_rows, akey, dim_api)
+ else:
+ h_list = html_media_name(html_tmc(brand, hkey, field_html))
+ p_list = api_media_bar(tmc_rows, akey, dim_api)
+ d = same_name_pct_diffs(h_list, p_list)
+ # one-side in top_n also counts as fail for media; for content/time skill focuses on same-name pct
+ if field_html in ("media_category", "media_name"):
+ h_names = {n for n, _ in h_list[:top_n]}
+ p_names = {n for n, _ in p_list[:top_n]}
+ # 「其他」 only on platform is noted but may not fail if not squeezing — skill says separate table
+ extra_p = p_names - h_names - {"其他"}
+ extra_h = h_names - p_names
+ if extra_p or extra_h:
+ ok = False
+ if d:
+ ok = False
+ diffs_by_plat[label] = (d, h_list, p_list)
+ results[num] = ok
+ sections.append(f"## {num}. {title} {mark(ok)}\n\n")
+ for label, (d, h_list, p_list) in diffs_by_plat.items():
+ if not d:
+ sections.append(f"{label}:画面上同名占比无差异。\n\n")
+ else:
+ sections.append(f"{label} 同名占比不同:\n\n")
+ sections.append("| 名称 | HTML 画面值 | 平台画面值 |\n|---|---|---|\n")
+ for name, hv, pv in d:
+ sections.append(f"| {name} | {hv}% | {pv}% |\n")
+ sections.append("\n")
+ if field_html in ("media_category", "media_name"):
+ side = one_side_rows(h_list, p_list, top_n)
+ # filter 其他-only platform note
+ other = [x for x in p_list if x[0] == "其他"]
+ if other and other[0][0] not in dict(h_list):
+ sections.append(
+ f"{label} 平台前 10 有「其他」={other[0][1]}%,HTML 不画「其他」。\n\n"
+ )
+ real_side = [s for s in side if s[0] != "其他" and s[2] != "其他"]
+ if real_side:
+ sections.append(f"{label} 仅一边进入前 {top_n}:\n\n")
+ sections.append("| HTML 名 | HTML 值 | 平台名 | 平台值 |\n|---|---|---|---|\n")
+ for s in real_side:
+ sections.append(f"| {s[0]} | {s[1]} | {s[2]} | {s[3]} |\n")
+ sections.append("\n")
+
+ emit_pct_section(7, "信源内容类型", "content_distribution", "content_type", 8)
+ emit_pct_section(8, "信源发布时间", "time_distribution", "time_distribution", 8, drop_no_time=True)
+ emit_pct_section(9, "媒体类型前 10", "media_category", "media_category", 10)
+ emit_pct_section(10, "媒体名称前 10", "media_name", "media_name", 10)
+
+ # --- 11 / 12 sources ---
+ i11_ok = True
+ i12_ok = True
+ i11_details = []
+ i12_details = []
+ for label, akey, hkey in PLATFORMS:
+ hs = html_sources(brand, hkey)
+ ps = api_sources(api["sources"][akey])
+ # 11: align by title set — channel + cite
+ h_by_title = {}
+ for x in hs:
+ t = str(x.get("title") or "")
+ h_by_title[t] = (
+ str(x.get("channel_name") or x.get("channel") or ""),
+ int(x.get("cite_count") or 0),
+ )
+ p_by_title = {x["title"]: (x["channel_name"], int(x["cite_count"])) for x in ps}
+ # set equality of titles
+ if set(h_by_title) != set(p_by_title):
+ # allow count mismatch when <30
+ if not (len(hs) < 30 and len(ps) < 30 and set(h_by_title) == set(p_by_title)):
+ if set(h_by_title) != set(p_by_title):
+ i11_ok = False
+ i11_details.append((label, "标题集合不同", len(hs), len(ps), len(set(h_by_title) ^ set(p_by_title))))
+ for t, (hc, hcite) in h_by_title.items():
+ if t not in p_by_title:
+ continue
+ pc, pcite = p_by_title[t]
+ if hc != pc or hcite != pcite:
+ i11_ok = False
+ i11_details.append((label, t[:40], f"{hc}/{hcite}", f"{pc}/{pcite}", ""))
+
+ # 12: order by index
+ n = min(30, len(hs), len(ps)) if hs and ps else min(30, max(len(hs), len(ps)))
+ # compare by position up to min length; different lengths fail
+ if len(hs) != len(ps) and not (len(hs) < 30 and len(ps) < 30 and len(hs) == len(ps)):
+ # if both truncated at available count and equal ok; else if counts differ fail 12
+ if len(hs) != len(ps):
+ i12_ok = False
+ for i in range(min(len(hs), len(ps), 30)):
+ ht = str(hs[i].get("title") or "")
+ pt = ps[i]["title"]
+ if ht != pt:
+ i12_ok = False
+ hc = int(hs[i].get("cite_count") or 0)
+ pc = int(ps[i]["cite_count"])
+ note = "并列换位,不是缺标题" if hc == pc else ""
+ i12_details.append((label, i + 1, ht[:50], pt[:50], hc, pc, note))
+
+ results[11] = i11_ok
+ results[12] = i12_ok
+ sections.append(f"## 11. 关联信源标题、渠道、被引次数 {mark(results[11])}\n\n")
+ sections.append("按标题对齐,不比序号。只取前 30。\n\n")
+ if results[11]:
+ sections.append("七个平台:标题集合及渠道、被引次数相同。\n\n")
+ else:
+ sections.append("| 平台 | 说明 | a | b | c |\n|---|---|---|---|---|\n")
+ for row in i11_details[:40]:
+ sections.append("| " + " | ".join(str(x) for x in row) + " |\n")
+ sections.append("\n")
+
+ sections.append(f"## 12. 关联信源标题序号 {mark(results[12])}\n\n")
+ sections.append("比画面序号上的标题。平台按 cite_count 降序稳定排序。\n\n")
+ if results[12]:
+ sections.append("七个平台:前 30 序号标题相同。\n\n")
+ else:
+ sections.append("| 平台 | 序号 | HTML 标题 | 平台标题 | HTML次数 | 平台次数 | 说明 |\n|---|---|---|---|---|---|---|\n")
+ for row in i12_details[:60]:
+ sections.append("| " + " | ".join(str(x) for x in row) + " |\n")
+ sections.append("\n")
+
+ overall = "一致" if all(results[i] for i in range(1, 13)) else "不完全一致"
+
+ # summary table
+ head = []
+ head.append("# 测试报告\n\n")
+ head.append(f"{overall}。\n\n")
+ head.append(
+ f"HTML 监测时间 {HTML_MONITOR_DATE} 对应平台监测周期 {PLATFORM_PERIOD}。"
+ "页面日期对应不是差异。HTML「综合」对平台「全平台」。"
+ "差超过 0.05 才算不同。排行榜只比各自 Top 10。\n\n"
+ )
+ head.append("## 参数\n\n")
+ head.append(f"- 平台:{platform_url}\n")
+ head.append(f"- HTML:{html_url}\n")
+ head.append(f"- url日期:{PLATFORM_PERIOD}\n")
+ head.append(f"- html日期:{HTML_MONITOR_DATE}\n")
+ head.append(f"- batchId:`{api.get('batchId')}`\n")
+ head.append(f"- 保存目录:{REPORT_DIR}\n\n")
+ head.append("## 十二项结论\n\n")
+ head.append("| 项 | 结果 |\n|---|---|\n")
+ labels = {
+ 1: "1 两个 URL 能否打开",
+ 2: "2 七个 AI 平台",
+ 3: "3 露出率、前三率、正面率",
+ 4: "4 分平台核心指标",
+ 5: "5 露出排行 · 各平台明细",
+ 6: "6 正面词、负面词",
+ 7: "7 信源内容类型",
+ 8: "8 信源发布时间",
+ 9: "9 媒体类型前 10",
+ 10: "10 媒体名称前 10",
+ 11: "11 关联信源标题、渠道、被引次数",
+ 12: "12 关联信源标题序号",
+ }
+ for i in range(1, 13):
+ head.append(f"| {labels[i]} | {mark(results[i])} |\n")
+ head.append("\n")
+
+ out_path = REPORT_DIR / f"测试报告-{report_id}-{pid}.md"
+ out_path.write_text("".join(head) + "".join(sections), encoding="utf-8")
+ return overall, out_path, all(results[i] for i in range(1, 13))
+
+
+def main() -> None:
+ batch = json.loads(BATCH.read_text(encoding="utf-8"))
+ lines = ["# batch_0830 汇总\n\n", "| project_id | 结论 | 报告 |\n|---|---|---|\n"]
+ for item in batch:
+ overall, path, ok = compare_project(item)
+ lines.append(f"| {item['project_id']} | {overall} | `{path.name}` |\n")
+ print(item["project_id"], overall, path, flush=True)
+ (REPORT_DIR / "_summary.md").write_text("".join(lines), encoding="utf-8")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/_summary.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/_summary.md
new file mode 100644
index 0000000..13bb598
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/_summary.md
@@ -0,0 +1,13 @@
+# batch_0906 汇总
+
+| project_id | 结论 | 报告 |
+|---|---|---|
+| 1169 | 不完全一致 | `测试报告-1-1169.md` |
+| 1170 | 一致 | `测试报告-1-1170.md` |
+| 1171 | 一致 | `测试报告-1-1171.md` |
+| 1173 | 一致 | `测试报告-1-1173.md` |
+| 1174 | 一致 | `测试报告-1-1174.md` |
+| 1177 | 一致 | `测试报告-1-1177.md` |
+| 1179 | 一致 | `测试报告-1-1179.md` |
+| 1187 | 一致 | `测试报告-1-1187.md` |
+| 1199 | 一致 | `测试报告-1-1199.md` |
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1169/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1169/html-open.png
new file mode 100644
index 0000000..800eacb
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1169/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1169/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1169/platform-open.png
new file mode 100644
index 0000000..24d375c
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1169/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1170/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1170/html-open.png
new file mode 100644
index 0000000..38dc79d
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1170/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1170/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1170/platform-open.png
new file mode 100644
index 0000000..928b954
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1170/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1171/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1171/html-open.png
new file mode 100644
index 0000000..a6bb4b5
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1171/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1171/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1171/platform-open.png
new file mode 100644
index 0000000..50abc23
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1171/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1173/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1173/html-open.png
new file mode 100644
index 0000000..cc88a98
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1173/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1173/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1173/platform-open.png
new file mode 100644
index 0000000..09563f5
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1173/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1174/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1174/html-open.png
new file mode 100644
index 0000000..b6e4702
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1174/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1174/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1174/platform-open.png
new file mode 100644
index 0000000..f55f024
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1174/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1177/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1177/html-open.png
new file mode 100644
index 0000000..8b1e411
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1177/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1177/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1177/platform-open.png
new file mode 100644
index 0000000..c1b61aa
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1177/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1179/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1179/html-open.png
new file mode 100644
index 0000000..fb99cb9
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1179/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1179/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1179/platform-open.png
new file mode 100644
index 0000000..0dbcd22
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1179/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1187/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1187/html-open.png
new file mode 100644
index 0000000..9f1c40b
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1187/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1187/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1187/platform-open.png
new file mode 100644
index 0000000..318ca8a
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1187/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1199/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1199/html-open.png
new file mode 100644
index 0000000..97cea86
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1199/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1199/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1199/platform-open.png
new file mode 100644
index 0000000..e70db6d
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/shots-1-1199/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1169.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1169.md
new file mode 100644
index 0000000..3343762
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1169.md
@@ -0,0 +1,169 @@
+# 测试报告
+
+不完全一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1169&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/52e7ca36-9acd-4b6a-8533-42352d1b00b9.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1169-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试失败❌ |
+| 12 关联信源标题序号 | 测试失败❌ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 卖点词。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 18.8% / 16.5% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 查博士 | 查博士 |
+| 3 | 懂车帝 | 懂车帝 |
+| 4 | 优信二手车 | 优信二手车 |
+| 5 | 澳康达 | 澳康达 |
+| 6 | 淘车二手车 | 淘车二手车 |
+| 7 | 闲鱼 | 闲鱼 |
+| 8 | 268V | 268V |
+| 9 | 检车家 | 检车家 |
+| 10 | 花乡 | 花乡 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试失败❌
+
+按标题对齐,不比序号。只取前 30。
+
+| 平台 | 说明 | a | b | c |
+|---|---|---|---|---|
+| 文心 | 标题集合不同 | 30 | 30 | 2 |
+
+## 12. 关联信源标题序号 测试失败❌
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+| 平台 | 序号 | HTML 标题 | 平台标题 | HTML次数 | 平台次数 | 说明 |
+|---|---|---|---|---|---|---|
+| 文心 | 30 | 一辆2024年买回来的新能源车,表显3万公里,落地价60万,车主把手续都备齐了,直接开到二手车市场准 | 一辆2024年买回来的新能源车,表显3万公里,落地价60万,车主把手续都备齐了,直接开到二手车市场准 | 1 | 1 | 并列换位,不是缺标题 |
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1170.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1170.md
new file mode 100644
index 0000000..e2fd868
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1170.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1170&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/a92d07ce-1e57-4dee-a2a5-ad893bd08806.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1170-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 购买场景词。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 19.8% / 15.6% / 99.7%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 优信二手车 | 优信二手车 |
+| 3 | 查博士 | 查博士 |
+| 4 | 懂车帝 | 懂车帝 |
+| 5 | 澳康达 | 澳康达 |
+| 6 | 淘车二手车 | 淘车二手车 |
+| 7 | 花乡 | 花乡 |
+| 8 | 人人车 | 人人车 |
+| 9 | 闲鱼 | 闲鱼 |
+| 10 | 汽车之家 | 汽车之家 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(3 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1171.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1171.md
new file mode 100644
index 0000000..65c3e89
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1171.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1171&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/216ef3e0-5c7a-4304-bf6e-e0d52e6c1c3d.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1171-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 价格词。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 6.4% / 6.4% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 懂车帝 | 懂车帝 |
+| 3 | 查博士 | 查博士 |
+| 4 | 淘车二手车 | 淘车二手车 |
+| 5 | 优信二手车 | 优信二手车 |
+| 6 | 闲鱼 | 闲鱼 |
+| 7 | 花乡 | 花乡 |
+| 8 | 人人车 | 人人车 |
+| 9 | 车300 | 车300 |
+| 10 | 汽车之家 | 汽车之家 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1173.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1173.md
new file mode 100644
index 0000000..75e7852
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1173.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1173&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/a57a0750-7305-4f27-888e-19387da469c4.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1173-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 口碑评价。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 100.0% / 99.7% / 87.7%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 卡泰驰 | 卡泰驰 |
+| 2 | 汽车之家 | 汽车之家 |
+| 3 | 查博士 | 查博士 |
+| 4 | 瓜子二手车 | 瓜子二手车 |
+| 5 | 懂车帝 | 懂车帝 |
+| 6 | 二手车之家 | 二手车之家 |
+| 7 | 优信二手车 | 优信二手车 |
+| 8 | 268V | 268V |
+| 9 | 澳康达 | 澳康达 |
+| 10 | 检车家 | 检车家 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(20 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1174.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1174.md
new file mode 100644
index 0000000..abd5631
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1174.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1174&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/8d1398b3-4214-4ef5-887d-d3286371a4b1.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1174-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 宝马。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 5.0% / 4.8% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 查博士 | 查博士 |
+| 3 | 懂车帝 | 懂车帝 |
+| 4 | 优信二手车 | 优信二手车 |
+| 5 | 检车家 | 检车家 |
+| 6 | 闲鱼 | 闲鱼 |
+| 7 | 澳康达 | 澳康达 |
+| 8 | 人人车 | 人人车 |
+| 9 | 花乡 | 花乡 |
+| 10 | 268V | 268V |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1177.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1177.md
new file mode 100644
index 0000000..45a877c
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1177.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1177&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/372c7809-01c5-4593-a976-c6baf78f79aa.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1177-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 奥迪。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 21.2% / 18.6% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 查博士 | 查博士 |
+| 3 | 优信二手车 | 优信二手车 |
+| 4 | 懂车帝 | 懂车帝 |
+| 5 | 闲鱼 | 闲鱼 |
+| 6 | 澳康达 | 澳康达 |
+| 7 | 卡泰驰 | 卡泰驰 |
+| 8 | 检车家 | 检车家 |
+| 9 | 车300 | 车300 |
+| 10 | 花乡 | 花乡 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1179.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1179.md
new file mode 100644
index 0000000..31f08db
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1179.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1179&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/20e26edc-3e46-4810-9a19-bd3d5638b243.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1179-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 新能源。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 12.8% / 10.2% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 转转 | 转转 |
+| 3 | 懂车帝 | 懂车帝 |
+| 4 | 闲鱼 | 闲鱼 |
+| 5 | 查博士 | 查博士 |
+| 6 | 优信二手车 | 优信二手车 |
+| 7 | 淘车二手车 | 淘车二手车 |
+| 8 | 澳康达 | 澳康达 |
+| 9 | 汽车之家 | 汽车之家 |
+| 10 | 帅车 | 帅车 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1187.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1187.md
new file mode 100644
index 0000000..e0f706c
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1187.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1187&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/7fd6a885-42b0-463e-ae86-c60a20655841.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1187-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 奔驰。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 9.8% / 9.3% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 查博士 | 查博士 |
+| 3 | 懂车帝 | 懂车帝 |
+| 4 | 优信二手车 | 优信二手车 |
+| 5 | 花乡 | 花乡 |
+| 6 | 闲鱼 | 闲鱼 |
+| 7 | 帅车 | 帅车 |
+| 8 | 澳康达 | 澳康达 |
+| 9 | 淘车二手车 | 淘车二手车 |
+| 10 | 人人车 | 人人车 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1199.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1199.md
new file mode 100644
index 0000000..277e006
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0906-test/测试报告-1-1199.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-06 对应平台监测周期 9月 W36。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-06&reportType=monitor&level=project&project=1199&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/b45ffa99-f2b2-44d4-b88f-7c2c50ad95bc.html
+- url日期:9月 W36
+- html日期:2026-09-06
+- batchId:`KATECHI-HIST-1199-20260906`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0906-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-06,项目为 竞品对比。平台页监测周期为 9月 W36。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 88.5% / 86.2% / 93.5%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 卡泰驰 | 卡泰驰 |
+| 2 | 帅车 | 帅车 |
+| 3 | 澳康达 | 澳康达 |
+| 4 | 优信二手车 | 优信二手车 |
+| 5 | 查博士 | 查博士 |
+| 6 | 58同城 | 58同城 |
+| 7 | 瓜子二手车 | 瓜子二手车 |
+| 8 | 汽车之家 | 汽车之家 |
+| 9 | 淘车二手车 | 淘车二手车 |
+| 10 | 懂车帝 | 懂车帝 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(20 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/_compare_l1.py b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/_compare_l1.py
new file mode 100644
index 0000000..93d0362
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/_compare_l1.py
@@ -0,0 +1,748 @@
+# -*- coding: utf-8 -*-
+"""L1 HTML vs platform screen-value compare for batch_0830."""
+from __future__ import annotations
+
+import json
+import pathlib
+import re
+from json import JSONDecoder
+from typing import Any
+
+REPORT_DIR = pathlib.Path(r"D:\test\灌数\卡泰驰\项目级\monitor-0920-test")
+HTML_DIR = REPORT_DIR / "_html"
+API_DIR = REPORT_DIR / "_api"
+BATCH = pathlib.Path(
+ r"D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\batch_0920.json"
+)
+
+PLATFORM_PERIOD = "9月 W38"
+HTML_MONITOR_DATE = "2026-09-20"
+TOL = 0.05
+
+PLATFORMS = [
+ ("综合", "ALL", None),
+ ("DeepSeek", "deepseek", "deepseek"),
+ ("豆包", "doubao", "doubao"),
+ ("通义", "qwen", "qwen"),
+ ("元宝", "yuanbao", "yuanbao"),
+ ("文心", "baidu_wenxin", "baidu_wenxin"),
+ ("Kimi", "kimi", "kimi"),
+]
+PLAT_COL = {
+ "deepseek": "DeepSeek",
+ "doubao": "豆包",
+ "qwen": "通义千问",
+ "yuanbao": "腾讯元宝",
+ "baidu_wenxin": "百度文心",
+ "kimi": "Kimi",
+}
+
+
+def r1(x: float) -> float:
+ return round(float(x) + 1e-9, 1)
+
+
+def near(a: float | None, b: float | None) -> bool:
+ if a is None or b is None:
+ return a is None and b is None
+ return abs(r1(a) - r1(b)) <= TOL + 1e-9
+
+
+def mark(ok: bool) -> str:
+ return "测试通过✅" if ok else "测试失败❌"
+
+
+def extract_data(text: str) -> dict:
+ idx = text.find("var DATA")
+ if idx < 0:
+ raise ValueError("no DATA")
+ brace = text.find("{", idx)
+ obj, _ = JSONDecoder().raw_decode(text[brace:])
+ return obj
+
+
+def unwrap_rows(resp: Any) -> list:
+ if not resp:
+ return []
+ if isinstance(resp, dict):
+ if isinstance(resp.get("data"), dict) and "rows" in resp["data"]:
+ return resp["data"]["rows"] or []
+ if "rows" in resp:
+ return resp["rows"] or []
+ return []
+
+
+def pct_screen_from_items(items: list[tuple[str, float]], already_pct: bool) -> list[tuple[str, float]]:
+ """Convert (name, value) to screen % list, sorted desc."""
+ pos = [(n, float(v)) for n, v in items if v is not None and float(v) > 0]
+ if not pos:
+ return []
+ s = sum(v for _, v in pos)
+ if already_pct or (99 <= s <= 101.5) or all(0 < v <= 100 for _, v in pos) and 99 <= s <= 101.5:
+ out = [(n, r1(v)) for n, v in pos]
+ else:
+ out = [(n, r1(v / s * 100)) for n, v in pos]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out
+
+
+def is_value_already_pct(values: list[float]) -> bool:
+ pos = [v for v in values if v and v > 0]
+ if not pos:
+ return True
+ s = sum(pos)
+ if 99 <= s <= 101.5:
+ return True
+ if all(0 < v <= 100 for v in pos) and 99 <= s <= 101.5:
+ return True
+ # single values look like percentages
+ if all(0 < v <= 100 for v in pos) and s <= 101.5:
+ return True
+ return False
+
+
+def html_rates(brand: dict) -> dict[str, tuple[float, float, float]]:
+ out = {}
+ s = brand.get("summary") or {}
+ out["ALL"] = (
+ float(s.get("avg_exposure_rate") or 0),
+ float(s.get("avg_top3_rate") or 0),
+ float(s.get("avg_positive_mention_rate") or 0),
+ )
+ for key, _, hkey in PLATFORMS[1:]:
+ self = ((brand.get("platforms") or {}).get(hkey) or {}).get("self") or {}
+ out[hkey] = (
+ float(self.get("exposure_rate") or 0),
+ float(self.get("top3_rate") or 0),
+ float(self.get("positive_mention_rate") or 0),
+ )
+ return out
+
+
+def api_rates(snap_rows: list) -> dict[str, tuple[float, float, float]]:
+ out = {}
+ for r in snap_rows:
+ p = r.get("platform")
+ m = r.get("metrics") or {}
+ out[p] = (
+ float(m.get("exposure_rate") or 0),
+ float(m.get("top3_rate") or 0),
+ float(m.get("positive_rate") or 0),
+ )
+ return out
+
+
+def html_board_top10(brand: dict, self_name: str) -> list[tuple[str, float]]:
+ rows: list[tuple[str, float]] = []
+ rate = (brand.get("summary") or {}).get("avg_exposure_rate")
+ if rate is not None:
+ rows.append((self_name, float(rate)))
+ for x in brand.get("core_competitors") or []:
+ name = x.get("product")
+ r = x.get("avg_exposure_rate")
+ if name is None or r is None:
+ continue
+ rows.append((str(name), float(r)))
+ rows.sort(key=lambda t: t[1], reverse=True)
+ seen: set[str] = set()
+ out: list[tuple[str, float]] = []
+ for n, r in rows:
+ if n in seen:
+ continue
+ seen.add(n)
+ out.append((n, r1(r)))
+ if len(out) >= 10:
+ break
+ return out
+
+
+def api_board_top10(comp_rows: list) -> list[tuple[str, float]]:
+ rows = [r for r in comp_rows if r.get("platform") == "ALL"]
+ scored = []
+ for r in rows:
+ name = r.get("competitor_name") or r.get("brand") or ""
+ er = (r.get("metrics") or {}).get("exposure_rate")
+ if name is None or er is None:
+ continue
+ scored.append((str(name), float(er)))
+ scored.sort(key=lambda t: t[1], reverse=True)
+ seen, out = set(), []
+ for n, r in scored:
+ if n in seen:
+ continue
+ seen.add(n)
+ out.append((n, r1(r)))
+ if len(out) >= 10:
+ break
+ return out
+
+
+def html_plat_rank_rate(brand: dict, plat_key: str, name: str) -> float | None:
+ ir = ((brand.get("platforms") or {}).get(plat_key) or {}).get("industry_ranking") or []
+ for x in ir:
+ if str(x.get("brand") or "") == name:
+ v = x.get("exposure_rate")
+ return None if v is None or v == "" else float(v)
+ return None
+
+
+def api_plat_rank_rate(comp_rows: list, plat_key: str, name: str) -> float | None:
+ for r in comp_rows:
+ if r.get("platform") != plat_key:
+ continue
+ if str(r.get("competitor_name") or "") != name:
+ continue
+ v = (r.get("metrics") or {}).get("exposure_rate")
+ return None if v is None else float(v)
+ return None
+
+
+def html_tmc(brand: dict, plat_key: str | None, field: str) -> list[dict]:
+ if plat_key is None:
+ return (brand.get("tmc_aggregate") or {}).get(field) or []
+ return (
+ ((brand.get("platforms") or {}).get(plat_key) or {}).get("citation") or {}
+ ).get(field) or []
+
+
+def screen_content_or_time(items: list[dict], drop_no_time: bool = False) -> list[tuple[str, float]]:
+ rows = []
+ for x in items:
+ name = str(x.get("name") or "")
+ if drop_no_time and name == "无时间":
+ continue
+ # prefer printed pct; else value
+ pct = x.get("pct")
+ val = x.get("value")
+ if pct is not None:
+ rows.append((name, float(pct)))
+ elif val is not None:
+ rows.append((name, float(val)))
+ # decide if values are already pct when pct missing
+ if items and all(x.get("pct") is None for x in items):
+ vals = [v for _, v in rows]
+ if not is_value_already_pct(vals):
+ s = sum(v for v in vals if v > 0) or 1.0
+ rows = [(n, v / s * 100 if v > 0 else 0.0) for n, v in rows]
+ rows = [(n, r1(v)) for n, v in rows if v and v > 0]
+ rows.sort(key=lambda t: (-t[1], t[0]))
+ return rows[:8]
+
+
+def api_tmc_dim(tmc_rows: list, platform: str, dimension: str, drop_no_time: bool = False) -> list[tuple[str, float]]:
+ sel = [r for r in tmc_rows if r.get("platform") == platform and r.get("dimension") == dimension]
+ items = []
+ for r in sel:
+ name = str(r.get("name") or "")
+ if drop_no_time and name == "无时间":
+ continue
+ v = r.get("value")
+ if v is None:
+ continue
+ items.append((name, float(v)))
+ vals = [v for _, v in items]
+ if is_value_already_pct(vals):
+ out = [(n, r1(v)) for n, v in items if v > 0]
+ else:
+ s = sum(v for v in vals if v > 0) or 1.0
+ out = [(n, r1(v / s * 100)) for n, v in items if v > 0]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out[:8]
+
+
+def html_media_type(items: list[dict]) -> list[tuple[str, float]]:
+ rows = []
+ for x in items:
+ name = str(x.get("name") or "")
+ if name in ("其他", "未知"):
+ continue
+ v = x.get("value")
+ if v is None:
+ continue
+ rows.append((name, float(v)))
+ s = sum(v for _, v in rows if v > 0) or 1.0
+ out = [(n, r1(v / s * 100)) for n, v in rows if v > 0]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out[:10]
+
+
+def html_media_name(items: list[dict]) -> list[tuple[str, float]]:
+ rows = []
+ for x in items:
+ name = str(x.get("name") or "")
+ if name in ("其他", "未知"):
+ continue
+ v = x.get("value")
+ if v is None:
+ continue
+ rows.append((name, float(v)))
+ s = sum(v for _, v in rows if v > 0) or 1.0
+ out = [(n, r1(v / s * 100)) for n, v in rows if v > 0]
+ out.sort(key=lambda t: (-t[1], t[0]))
+ return out[:10]
+
+
+def api_media_bar(tmc_rows: list, platform: str, dimension: str) -> list[tuple[str, float]]:
+ sel = [r for r in tmc_rows if r.get("platform") == platform and r.get("dimension") == dimension]
+ items = [(str(r.get("name") or ""), float(r.get("value") or 0)) for r in sel]
+ items = [(n, v) for n, v in items if n and v > 0]
+ items.sort(key=lambda t: (-t[1], t[0]))
+ top = items[:10]
+ s = sum(v for _, v in top)
+ if s <= 101.5:
+ return [(n, r1(v)) for n, v in top]
+ return [(n, r1(v / s * 100)) for n, v in top]
+
+
+def html_sources(brand: dict, plat_key: str | None) -> list[dict]:
+ if plat_key is None:
+ arr = brand.get("source_top30") or []
+ else:
+ arr = ((brand.get("platforms") or {}).get(plat_key) or {}).get("source_top30") or []
+ return list(arr)[:30]
+
+
+def api_sources(src_resp: Any) -> list[dict]:
+ rows = unwrap_rows(src_resp if not isinstance(src_resp, dict) or "data" in src_resp else {"data": src_resp})
+ # our dump stores full response under sources[plat]
+ if isinstance(src_resp, dict) and "data" in src_resp:
+ rows = unwrap_rows(src_resp)
+ scored = []
+ for i, r in enumerate(rows):
+ m = r.get("metrics") or {}
+ cite = m.get("cite_count")
+ if cite is None:
+ cite = r.get("cite_count") or 0
+ scored.append((float(cite), i, r))
+ scored.sort(key=lambda t: (-t[0], t[1]))
+ out = []
+ for cite, _, r in scored[:30]:
+ out.append(
+ {
+ "title": str(r.get("title") or ""),
+ "channel_name": str(r.get("channel_name") or ""),
+ "cite_count": int(cite) if float(cite).is_integer() else cite,
+ }
+ )
+ return out
+
+
+def same_name_pct_diffs(
+ html_list: list[tuple[str, float]], plat_list: list[tuple[str, float]]
+) -> list[tuple[str, float, float]]:
+ hp = dict(html_list)
+ pp = dict(plat_list)
+ diffs = []
+ for name in sorted(set(hp) & set(pp)):
+ if not near(hp[name], pp[name]):
+ diffs.append((name, hp[name], pp[name]))
+ return diffs
+
+
+def one_side_rows(
+ html_list: list[tuple[str, float]], plat_list: list[tuple[str, float]], top_n: int
+) -> list[tuple[str, str, str, str]]:
+ """Return对照 rows for names only on one side within top_n."""
+ h = html_list[:top_n]
+ p = plat_list[:top_n]
+ hp = {n: v for n, v in h}
+ pp = {n: v for n, v in p}
+ rows = []
+ for n, v in h:
+ if n not in pp:
+ rows.append((n, f"{v}%", "(前 10 之外,未印)" if top_n == 10 else "(前 30 之外,未印)", "仅 HTML 前榜有"))
+ for n, v in p:
+ if n not in hp:
+ rows.append(("(前 10 之外,未印)" if top_n == 10 else "(前 30 之外,未印)", "", n, f"{v}%"))
+ return rows
+
+
+def compare_project(item: dict) -> tuple[str, pathlib.Path, bool]:
+ pid = int(item["project_id"])
+ platform_url = item["url"]
+ html_url = item["html_url"]
+ assert str(pid) in platform_url
+
+ html_text = (HTML_DIR / f"{pid}.html").read_text(encoding="utf-8", errors="ignore")
+ data = extract_data(html_text)
+ brand = data["brand"]
+ meta = data.get("meta") or {}
+ self_name = str(meta.get("brand") or brand.get("label") or "卡泰驰")
+ api = json.loads((API_DIR / f"{pid}.json").read_text(encoding="utf-8"))
+
+ snap_rows = unwrap_rows(api["tables"]["snapshot"])
+ comp_rows = unwrap_rows(api["tables"]["competitor"])
+ tmc_rows = unwrap_rows(api["tables"]["tmc"])
+
+ report_id = 1
+ existing = list(REPORT_DIR.glob(f"测试报告-*-{pid}.md"))
+ if existing:
+ nums = []
+ for f in existing:
+ m = re.match(rf"测试报告-(\d+)-{pid}\.md$", f.name)
+ if m:
+ nums.append(int(m.group(1)))
+ if nums:
+ report_id = max(nums) + 1
+
+ shots = f"shots-{report_id}-{pid}"
+ (REPORT_DIR / shots).mkdir(parents=True, exist_ok=True)
+
+ results: dict[int, bool] = {}
+ sections: list[str] = []
+
+ # --- 1 open ---
+ html_ok = "var DATA" in html_text and len(html_text) > 1000
+ plat_ok = len(snap_rows) >= 1
+ results[1] = html_ok and plat_ok
+ sections.append(f"## 1. 页面打开 {mark(results[1])}\n\n")
+ sections.append(
+ f"两个 URL 都能打开。HTML 页头监测日期对应 {HTML_MONITOR_DATE},项目为 {meta.get('subtitle_product') or meta.get('question') or self_name}。"
+ f"平台页监测周期为 {PLATFORM_PERIOD}。\n\n"
+ )
+ sections.append(f"\n\n")
+ sections.append(f"\n\n")
+
+ # --- 2 platforms ---
+ results[2] = True # 约定映射
+ sections.append("## 2. 七个 AI 平台 测试通过✅\n\n")
+ sections.append(
+ "综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。\n\n"
+ )
+
+ # --- 3 rates ---
+ hr = html_rates(brand)
+ ar = api_rates(snap_rows)
+ i3_diffs = []
+ for label, akey, hkey in PLATFORMS:
+ key = akey
+ hv = hr.get(hkey if hkey else "ALL") or hr.get("ALL")
+ # fix mapping
+ if hkey is None:
+ hv = hr["ALL"]
+ else:
+ hv = hr[hkey]
+ pv = ar.get(akey)
+ if pv is None:
+ i3_diffs.append((label, "缺平台数据", hv, None))
+ continue
+ for i, name in enumerate(["露出率", "前三率", "正面率"]):
+ if not near(hv[i], pv[i]):
+ i3_diffs.append((label, name, hv[i], pv[i]))
+ results[3] = not i3_diffs
+ sections.append(f"## 3. 露出率、前三率、正面率 {mark(results[3])}\n\n")
+ if results[3]:
+ s = hr["ALL"]
+ sections.append(
+ f"7 个平台相同。综合为 {r1(s[0])}% / {r1(s[1])}% / {r1(s[2])}%。\n\n"
+ "综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。\n\n"
+ )
+ else:
+ sections.append("| 平台 | 指标 | HTML | 平台 |\n|---|---|---|---|\n")
+ for row in i3_diffs:
+ sections.append(f"| {row[0]} | {row[1]} | {row[2]} | {row[3]} |\n")
+ sections.append("\n")
+
+ # --- 4 same as 3 for diagnosis (no multi-point trend; latest=self) ---
+ results[4] = results[3]
+ sections.append(f"## 4. 分平台核心指标 {mark(results[4])}\n\n")
+ sections.append(
+ "本批为 diagnosis,HTML 各平台 `self` 最新点对平台 snapshot 分平台三项。"
+ "综合覆盖六个平台的这三个点。\n\n"
+ )
+ if results[4]:
+ sections.append("综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。\n\n")
+ else:
+ sections.append("与第 3 项相同差异,见上表。\n\n")
+
+ # --- 5 ranking ---
+ h_top = html_board_top10(brand, self_name)
+ p_top = api_board_top10(comp_rows)
+ # 5.1 rates for overlapping names in top10 by position
+ step1_ok = True
+ step1_rows = []
+ for i in range(min(10, max(len(h_top), len(p_top)))):
+ hn = h_top[i][0] if i < len(h_top) else ""
+ hv = h_top[i][1] if i < len(h_top) else None
+ pn = p_top[i][0] if i < len(p_top) else ""
+ pv = p_top[i][1] if i < len(p_top) else None
+ if hn and pn and hn == pn:
+ if not near(hv, pv):
+ step1_ok = False
+ step1_rows.append((i + 1, hn, hv, pv))
+ elif hn != pn:
+ step1_ok = False
+ step1_rows.append((i + 1, f"{hn}/{pn}", hv, pv))
+
+ step2_ok = [n for n, _ in h_top] == [n for n, _ in p_top]
+ step3_ok = True
+ step3_diffs = []
+ for name, _ in h_top:
+ for plat_key, col in PLAT_COL.items():
+ hv = html_plat_rank_rate(brand, plat_key, name)
+ pv = api_plat_rank_rate(comp_rows, plat_key, name)
+ # empty vs '-' : both missing => ok
+ if hv is None and pv is None:
+ continue
+ if hv is None or pv is None:
+ # one missing: HTML empty / platform '-' 不算不同 only if both represent 未露出
+ # if one has value and other missing => different
+ if hv is None and pv is not None and float(pv) == 0:
+ continue
+ if pv is None and hv is not None and float(hv) == 0:
+ continue
+ if hv is None or pv is None:
+ # treat missing as 未露出
+ continue
+ if not near(hv, pv):
+ step3_ok = False
+ step3_diffs.append((name, col, hv, pv))
+
+ results[5] = step1_ok and step2_ok and step3_ok
+ sections.append(f"## 5. 露出排行 · 各平台明细 {mark(results[5])}\n\n")
+ sections.append(
+ "HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。"
+ "两边按平均露出率降序取 Top 10。\n\n"
+ )
+ sections.append(f"### 5.1 综合平均露出率对全平台列 {mark(step1_ok)}\n\n")
+ if step1_ok:
+ sections.append("Top 10 同名露出率无差异。\n\n")
+ else:
+ sections.append("| 排名 | 品牌 | HTML | 平台 |\n|---|---|---|---|\n")
+ for r in step1_rows:
+ sections.append(f"| {r[0]} | {r[1]} | {r[2]} | {r[3]} |\n")
+ sections.append("\n")
+
+ sections.append(f"### 5.2 综合 Top 10 名次和品牌名 {mark(step2_ok)}\n\n")
+ sections.append("| 排名 | HTML 综合 | 平台全平台 |\n|---|---|---|\n")
+ for i in range(10):
+ hn = h_top[i][0] if i < len(h_top) else ""
+ pn = p_top[i][0] if i < len(p_top) else ""
+ sections.append(f"| {i+1} | {hn} | {pn} |\n")
+ sections.append("\n")
+
+ sections.append(f"### 5.3 Top10 品牌分平台露出率 {mark(step3_ok)}\n\n")
+ if step3_ok:
+ sections.append("DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。\n\n")
+ else:
+ sections.append("| 品牌 | 平台列 | HTML | 平台 |\n|---|---|---|---|\n")
+ for r in step3_diffs[:50]:
+ sections.append(f"| {r[0]} | {r[1]} | {r[2]} | {r[3]} |\n")
+ sections.append("\n")
+
+ # --- 6 wordcloud ---
+ h_pos = {str(x.get("word")) for x in (brand.get("wordcloud") or {}).get("positive") or []}
+ h_neg = {str(x.get("word")) for x in (brand.get("wordcloud") or {}).get("negative") or []}
+ wc_data = (api.get("wordcloud") or {}).get("data") or {}
+ words = wc_data.get("words") or []
+ p_pos = {str(w.get("word")) for w in words if (w.get("sentiment") or "").lower() == "positive"}
+ p_neg = {str(w.get("word")) for w in words if (w.get("sentiment") or "").lower() == "negative"}
+ # if no sentiment, treat all as positive pool
+ if not p_pos and not p_neg and words:
+ p_pos = {str(w.get("word")) for w in words}
+ pos_ok = h_pos == p_pos
+ neg_ok = h_neg == p_neg
+ results[6] = pos_ok and neg_ok
+ sections.append(f"## 6. 正面词、负面词 {mark(results[6])}\n\n")
+ sections.append(
+ "文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;"
+ "未监测到负面词=中正面率100%,暂无负面词。\n\n"
+ )
+ if results[6]:
+ sections.append(
+ f"正面词条相同({len(h_pos)} 个)。"
+ + ("两边均无负面词。" if not h_neg else f"负面词条相同({len(h_neg)} 个)。")
+ + "\n\n"
+ )
+ else:
+ only_h = sorted(h_pos - p_pos)
+ only_p = sorted(p_pos - h_pos)
+ sections.append(f"正面词仅 HTML:{only_h[:20]}\n\n正面词仅平台:{only_p[:20]}\n\n")
+ if h_neg != p_neg:
+ sections.append(f"负面词仅 HTML:{sorted(h_neg-p_neg)}\n\n负面词仅平台:{sorted(p_neg-h_neg)}\n\n")
+
+ # helpers for 7-10
+ def emit_pct_section(num: int, title: str, field_html: str, dim_api: str, top_n: int, drop_no_time: bool = False):
+ diffs_by_plat = {}
+ ok = True
+ for label, akey, hkey in PLATFORMS:
+ if field_html in ("content_distribution", "time_distribution"):
+ h_list = screen_content_or_time(html_tmc(brand, hkey, field_html), drop_no_time=drop_no_time)
+ p_list = api_tmc_dim(tmc_rows, akey, dim_api, drop_no_time=drop_no_time)
+ elif field_html == "media_category":
+ h_list = html_media_type(html_tmc(brand, hkey, field_html))
+ p_list = api_media_bar(tmc_rows, akey, dim_api)
+ else:
+ h_list = html_media_name(html_tmc(brand, hkey, field_html))
+ p_list = api_media_bar(tmc_rows, akey, dim_api)
+ d = same_name_pct_diffs(h_list, p_list)
+ # one-side in top_n also counts as fail for media; for content/time skill focuses on same-name pct
+ if field_html in ("media_category", "media_name"):
+ h_names = {n for n, _ in h_list[:top_n]}
+ p_names = {n for n, _ in p_list[:top_n]}
+ # 「其他」 only on platform is noted but may not fail if not squeezing — skill says separate table
+ extra_p = p_names - h_names - {"其他"}
+ extra_h = h_names - p_names
+ if extra_p or extra_h:
+ ok = False
+ if d:
+ ok = False
+ diffs_by_plat[label] = (d, h_list, p_list)
+ results[num] = ok
+ sections.append(f"## {num}. {title} {mark(ok)}\n\n")
+ for label, (d, h_list, p_list) in diffs_by_plat.items():
+ if not d:
+ sections.append(f"{label}:画面上同名占比无差异。\n\n")
+ else:
+ sections.append(f"{label} 同名占比不同:\n\n")
+ sections.append("| 名称 | HTML 画面值 | 平台画面值 |\n|---|---|---|\n")
+ for name, hv, pv in d:
+ sections.append(f"| {name} | {hv}% | {pv}% |\n")
+ sections.append("\n")
+ if field_html in ("media_category", "media_name"):
+ side = one_side_rows(h_list, p_list, top_n)
+ # filter 其他-only platform note
+ other = [x for x in p_list if x[0] == "其他"]
+ if other and other[0][0] not in dict(h_list):
+ sections.append(
+ f"{label} 平台前 10 有「其他」={other[0][1]}%,HTML 不画「其他」。\n\n"
+ )
+ real_side = [s for s in side if s[0] != "其他" and s[2] != "其他"]
+ if real_side:
+ sections.append(f"{label} 仅一边进入前 {top_n}:\n\n")
+ sections.append("| HTML 名 | HTML 值 | 平台名 | 平台值 |\n|---|---|---|---|\n")
+ for s in real_side:
+ sections.append(f"| {s[0]} | {s[1]} | {s[2]} | {s[3]} |\n")
+ sections.append("\n")
+
+ emit_pct_section(7, "信源内容类型", "content_distribution", "content_type", 8)
+ emit_pct_section(8, "信源发布时间", "time_distribution", "time_distribution", 8, drop_no_time=True)
+ emit_pct_section(9, "媒体类型前 10", "media_category", "media_category", 10)
+ emit_pct_section(10, "媒体名称前 10", "media_name", "media_name", 10)
+
+ # --- 11 / 12 sources ---
+ i11_ok = True
+ i12_ok = True
+ i11_details = []
+ i12_details = []
+ for label, akey, hkey in PLATFORMS:
+ hs = html_sources(brand, hkey)
+ ps = api_sources(api["sources"][akey])
+ # 11: align by title set — channel + cite
+ h_by_title = {}
+ for x in hs:
+ t = str(x.get("title") or "")
+ h_by_title[t] = (
+ str(x.get("channel_name") or x.get("channel") or ""),
+ int(x.get("cite_count") or 0),
+ )
+ p_by_title = {x["title"]: (x["channel_name"], int(x["cite_count"])) for x in ps}
+ # set equality of titles
+ if set(h_by_title) != set(p_by_title):
+ # allow count mismatch when <30
+ if not (len(hs) < 30 and len(ps) < 30 and set(h_by_title) == set(p_by_title)):
+ if set(h_by_title) != set(p_by_title):
+ i11_ok = False
+ i11_details.append((label, "标题集合不同", len(hs), len(ps), len(set(h_by_title) ^ set(p_by_title))))
+ for t, (hc, hcite) in h_by_title.items():
+ if t not in p_by_title:
+ continue
+ pc, pcite = p_by_title[t]
+ if hc != pc or hcite != pcite:
+ i11_ok = False
+ i11_details.append((label, t[:40], f"{hc}/{hcite}", f"{pc}/{pcite}", ""))
+
+ # 12: order by index
+ n = min(30, len(hs), len(ps)) if hs and ps else min(30, max(len(hs), len(ps)))
+ # compare by position up to min length; different lengths fail
+ if len(hs) != len(ps) and not (len(hs) < 30 and len(ps) < 30 and len(hs) == len(ps)):
+ # if both truncated at available count and equal ok; else if counts differ fail 12
+ if len(hs) != len(ps):
+ i12_ok = False
+ for i in range(min(len(hs), len(ps), 30)):
+ ht = str(hs[i].get("title") or "")
+ pt = ps[i]["title"]
+ if ht != pt:
+ i12_ok = False
+ hc = int(hs[i].get("cite_count") or 0)
+ pc = int(ps[i]["cite_count"])
+ note = "并列换位,不是缺标题" if hc == pc else ""
+ i12_details.append((label, i + 1, ht[:50], pt[:50], hc, pc, note))
+
+ results[11] = i11_ok
+ results[12] = i12_ok
+ sections.append(f"## 11. 关联信源标题、渠道、被引次数 {mark(results[11])}\n\n")
+ sections.append("按标题对齐,不比序号。只取前 30。\n\n")
+ if results[11]:
+ sections.append("七个平台:标题集合及渠道、被引次数相同。\n\n")
+ else:
+ sections.append("| 平台 | 说明 | a | b | c |\n|---|---|---|---|---|\n")
+ for row in i11_details[:40]:
+ sections.append("| " + " | ".join(str(x) for x in row) + " |\n")
+ sections.append("\n")
+
+ sections.append(f"## 12. 关联信源标题序号 {mark(results[12])}\n\n")
+ sections.append("比画面序号上的标题。平台按 cite_count 降序稳定排序。\n\n")
+ if results[12]:
+ sections.append("七个平台:前 30 序号标题相同。\n\n")
+ else:
+ sections.append("| 平台 | 序号 | HTML 标题 | 平台标题 | HTML次数 | 平台次数 | 说明 |\n|---|---|---|---|---|---|---|\n")
+ for row in i12_details[:60]:
+ sections.append("| " + " | ".join(str(x) for x in row) + " |\n")
+ sections.append("\n")
+
+ overall = "一致" if all(results[i] for i in range(1, 13)) else "不完全一致"
+
+ # summary table
+ head = []
+ head.append("# 测试报告\n\n")
+ head.append(f"{overall}。\n\n")
+ head.append(
+ f"HTML 监测时间 {HTML_MONITOR_DATE} 对应平台监测周期 {PLATFORM_PERIOD}。"
+ "页面日期对应不是差异。HTML「综合」对平台「全平台」。"
+ "差超过 0.05 才算不同。排行榜只比各自 Top 10。\n\n"
+ )
+ head.append("## 参数\n\n")
+ head.append(f"- 平台:{platform_url}\n")
+ head.append(f"- HTML:{html_url}\n")
+ head.append(f"- url日期:{PLATFORM_PERIOD}\n")
+ head.append(f"- html日期:{HTML_MONITOR_DATE}\n")
+ head.append(f"- batchId:`{api.get('batchId')}`\n")
+ head.append(f"- 保存目录:{REPORT_DIR}\n\n")
+ head.append("## 十二项结论\n\n")
+ head.append("| 项 | 结果 |\n|---|---|\n")
+ labels = {
+ 1: "1 两个 URL 能否打开",
+ 2: "2 七个 AI 平台",
+ 3: "3 露出率、前三率、正面率",
+ 4: "4 分平台核心指标",
+ 5: "5 露出排行 · 各平台明细",
+ 6: "6 正面词、负面词",
+ 7: "7 信源内容类型",
+ 8: "8 信源发布时间",
+ 9: "9 媒体类型前 10",
+ 10: "10 媒体名称前 10",
+ 11: "11 关联信源标题、渠道、被引次数",
+ 12: "12 关联信源标题序号",
+ }
+ for i in range(1, 13):
+ head.append(f"| {labels[i]} | {mark(results[i])} |\n")
+ head.append("\n")
+
+ out_path = REPORT_DIR / f"测试报告-{report_id}-{pid}.md"
+ out_path.write_text("".join(head) + "".join(sections), encoding="utf-8")
+ return overall, out_path, all(results[i] for i in range(1, 13))
+
+
+def main() -> None:
+ batch = json.loads(BATCH.read_text(encoding="utf-8"))
+ lines = ["# batch_0830 汇总\n\n", "| project_id | 结论 | 报告 |\n|---|---|---|\n"]
+ for item in batch:
+ overall, path, ok = compare_project(item)
+ lines.append(f"| {item['project_id']} | {overall} | `{path.name}` |\n")
+ print(item["project_id"], overall, path, flush=True)
+ (REPORT_DIR / "_summary.md").write_text("".join(lines), encoding="utf-8")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/_summary.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/_summary.md
new file mode 100644
index 0000000..0210787
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/_summary.md
@@ -0,0 +1,13 @@
+# batch_0920 汇总
+
+| project_id | 结论 | 报告 |
+|---|---|---|
+| 1169 | 一致 | `测试报告-1-1169.md` |
+| 1170 | 不完全一致 | `测试报告-1-1170.md` |
+| 1171 | 一致 | `测试报告-1-1171.md` |
+| 1173 | 一致 | `测试报告-1-1173.md` |
+| 1174 | 一致 | `测试报告-1-1174.md` |
+| 1177 | 一致 | `测试报告-1-1177.md` |
+| 1179 | 一致 | `测试报告-1-1179.md` |
+| 1187 | 一致 | `测试报告-1-1187.md` |
+| 1199 | 一致 | `测试报告-1-1199.md` |
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1169/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1169/html-open.png
new file mode 100644
index 0000000..4e24769
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1169/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1169/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1169/platform-open.png
new file mode 100644
index 0000000..496caa1
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1169/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1170/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1170/html-open.png
new file mode 100644
index 0000000..24ffa63
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1170/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1170/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1170/platform-open.png
new file mode 100644
index 0000000..56f294a
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1170/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1171/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1171/html-open.png
new file mode 100644
index 0000000..1734c9b
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1171/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1171/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1171/platform-open.png
new file mode 100644
index 0000000..77bae4d
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1171/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1173/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1173/html-open.png
new file mode 100644
index 0000000..c186b7f
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1173/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1173/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1173/platform-open.png
new file mode 100644
index 0000000..2881c73
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1173/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1174/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1174/html-open.png
new file mode 100644
index 0000000..249aacb
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1174/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1174/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1174/platform-open.png
new file mode 100644
index 0000000..8ab334a
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1174/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1177/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1177/html-open.png
new file mode 100644
index 0000000..24da916
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1177/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1177/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1177/platform-open.png
new file mode 100644
index 0000000..3816a91
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1177/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1179/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1179/html-open.png
new file mode 100644
index 0000000..c3084d1
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1179/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1179/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1179/platform-open.png
new file mode 100644
index 0000000..976755e
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1179/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1187/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1187/html-open.png
new file mode 100644
index 0000000..2e95797
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1187/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1187/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1187/platform-open.png
new file mode 100644
index 0000000..bad5719
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1187/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1199/html-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1199/html-open.png
new file mode 100644
index 0000000..42b1a1d
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1199/html-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1199/platform-open.png b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1199/platform-open.png
new file mode 100644
index 0000000..030aa39
Binary files /dev/null and b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/shots-1-1199/platform-open.png differ
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1169.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1169.md
new file mode 100644
index 0000000..e78feef
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1169.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1169&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/3899e673-cd92-4670-8203-566cee53a121.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1169-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 卖点词。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 29.6% / 26.8% / 99.2%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 查博士 | 查博士 |
+| 3 | 懂车帝 | 懂车帝 |
+| 4 | 优信二手车 | 优信二手车 |
+| 5 | 花乡 | 花乡 |
+| 6 | 卡泰驰 | 卡泰驰 |
+| 7 | 澳康达 | 澳康达 |
+| 8 | 淘车二手车 | 淘车二手车 |
+| 9 | 268V | 268V |
+| 10 | 闲鱼 | 闲鱼 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(2 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1170.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1170.md
new file mode 100644
index 0000000..a668add
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1170.md
@@ -0,0 +1,171 @@
+# 测试报告
+
+不完全一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1170&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/b4007bdb-5138-4097-ba18-79b53fdc9c35.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1170-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试失败❌ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 购买场景词。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 25.7% / 22.4% / 99.7%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 花乡 | 花乡 |
+| 3 | 优信二手车 | 优信二手车 |
+| 4 | 懂车帝 | 懂车帝 |
+| 5 | 查博士 | 查博士 |
+| 6 | 淘车二手车 | 淘车二手车 |
+| 7 | 澳康达 | 澳康达 |
+| 8 | 闲鱼 | 闲鱼 |
+| 9 | 卡泰驰 | 卡泰驰 |
+| 10 | 汽车之家 | 汽车之家 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(6 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试失败❌
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+文心 仅一边进入前 10:
+
+| HTML 名 | HTML 值 | 平台名 | 平台值 |
+|---|---|---|---|
+| 政府机构官网 | 0.0% | (前 10 之外,未印) | 仅 HTML 前榜有 |
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1171.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1171.md
new file mode 100644
index 0000000..8daf433
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1171.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1171&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/90f82b55-5c3d-480e-991f-c96d6dfc96dc.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1171-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 价格词。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 10.1% / 9.5% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 懂车帝 | 懂车帝 |
+| 3 | 花乡 | 花乡 |
+| 4 | 闲鱼 | 闲鱼 |
+| 5 | 查博士 | 查博士 |
+| 6 | 淘车二手车 | 淘车二手车 |
+| 7 | 优信二手车 | 优信二手车 |
+| 8 | 人人车 | 人人车 |
+| 9 | 天天拍车 | 天天拍车 |
+| 10 | 汽车之家 | 汽车之家 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1173.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1173.md
new file mode 100644
index 0000000..0192d8c
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1173.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1173&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/8507f96c-d167-45f9-bd78-0958bc99fba0.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1173-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 口碑评价。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 95.0% / 95.0% / 86.5%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 卡泰驰 | 卡泰驰 |
+| 2 | 汽车之家 | 汽车之家 |
+| 3 | 查博士 | 查博士 |
+| 4 | 懂车帝 | 懂车帝 |
+| 5 | 瓜子二手车 | 瓜子二手车 |
+| 6 | 二手车之家 | 二手车之家 |
+| 7 | 优信二手车 | 优信二手车 |
+| 8 | 检车家 | 检车家 |
+| 9 | 澳康达 | 澳康达 |
+| 10 | 268V | 268V |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(20 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1174.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1174.md
new file mode 100644
index 0000000..08e3ee3
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1174.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1174&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/03a274fd-74e2-4fc8-bcc5-88b5286016f8.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1174-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 宝马。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 13.8% / 12.6% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 懂车帝 | 懂车帝 |
+| 3 | 查博士 | 查博士 |
+| 4 | 优信二手车 | 优信二手车 |
+| 5 | 花乡 | 花乡 |
+| 6 | 268V | 268V |
+| 7 | 汽车之家 | 汽车之家 |
+| 8 | 闲鱼 | 闲鱼 |
+| 9 | 澳康达 | 澳康达 |
+| 10 | 卡泰驰 | 卡泰驰 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1177.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1177.md
new file mode 100644
index 0000000..c3ab848
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1177.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1177&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/a5fc2516-2de6-41ab-85a1-67a94bde2181.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1177-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 奥迪。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 35.5% / 34.5% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 澳康达 | 澳康达 |
+| 3 | 卡泰驰 | 卡泰驰 |
+| 4 | 查博士 | 查博士 |
+| 5 | 懂车帝 | 懂车帝 |
+| 6 | 优信二手车 | 优信二手车 |
+| 7 | 闲鱼 | 闲鱼 |
+| 8 | 花乡 | 花乡 |
+| 9 | 检车家 | 检车家 |
+| 10 | 268V | 268V |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1179.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1179.md
new file mode 100644
index 0000000..f757561
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1179.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1179&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/74a34826-4088-4b8e-8b7d-4fdf12007e8b.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1179-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 新能源。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 20.0% / 17.4% / 100.0%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 懂车帝 | 懂车帝 |
+| 3 | 转转 | 转转 |
+| 4 | 查博士 | 查博士 |
+| 5 | 淘车二手车 | 淘车二手车 |
+| 6 | 闲鱼 | 闲鱼 |
+| 7 | 优信二手车 | 优信二手车 |
+| 8 | 花乡 | 花乡 |
+| 9 | 卡泰驰 | 卡泰驰 |
+| 10 | 帅车 | 帅车 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。两边均无负面词。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1187.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1187.md
new file mode 100644
index 0000000..d012752
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1187.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1187&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/ef43ba7c-5d22-4df7-99b9-9697d5095f67.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1187-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 奔驰。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 28.8% / 28.3% / 96.7%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 瓜子二手车 | 瓜子二手车 |
+| 2 | 查博士 | 查博士 |
+| 3 | 懂车帝 | 懂车帝 |
+| 4 | 花乡 | 花乡 |
+| 5 | 卡泰驰 | 卡泰驰 |
+| 6 | 澳康达 | 澳康达 |
+| 7 | 优信二手车 | 优信二手车 |
+| 8 | 闲鱼 | 闲鱼 |
+| 9 | 检车家 | 检车家 |
+| 10 | 人人车 | 人人车 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(3 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+
diff --git a/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1199.md b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1199.md
new file mode 100644
index 0000000..d0c1583
--- /dev/null
+++ b/haoxian_kataichi/skills/L1-geo-html-screen-diff/monitor-0920-test/测试报告-1-1199.md
@@ -0,0 +1,165 @@
+# 测试报告
+
+一致。
+
+HTML 监测时间 2026-09-20 对应平台监测周期 9月 W38。页面日期对应不是差异。HTML「综合」对平台「全平台」。差超过 0.05 才算不同。排行榜只比各自 Top 10。
+
+## 参数
+
+- 平台:https://haoxian.cemeta.cn/geo-monitor?batchDate=2026-09-20&reportType=monitor&level=project&project=1199&line=%E5%8D%A1%E6%B3%B0%E9%A9%B0::%E6%B1%BD%E8%BD%A6%E5%B9%B3%E5%8F%B0
+- HTML:https://cemeta-resource-1313090634.cos.ap-beijing.myqcloud.com/workflow/bc21a4ab-c882-4868-adfb-829c649bf6a0.html
+- url日期:9月 W38
+- html日期:2026-09-20
+- batchId:`KATECHI-HIST-1199-20260920`
+- 保存目录:D:\test\haoxian-script\haoxian_kataichi\skills\L1-geo-html-screen-diff\monitor-0920-test
+
+## 十二项结论
+
+| 项 | 结果 |
+|---|---|
+| 1 两个 URL 能否打开 | 测试通过✅ |
+| 2 七个 AI 平台 | 测试通过✅ |
+| 3 露出率、前三率、正面率 | 测试通过✅ |
+| 4 分平台核心指标 | 测试通过✅ |
+| 5 露出排行 · 各平台明细 | 测试通过✅ |
+| 6 正面词、负面词 | 测试通过✅ |
+| 7 信源内容类型 | 测试通过✅ |
+| 8 信源发布时间 | 测试通过✅ |
+| 9 媒体类型前 10 | 测试通过✅ |
+| 10 媒体名称前 10 | 测试通过✅ |
+| 11 关联信源标题、渠道、被引次数 | 测试通过✅ |
+| 12 关联信源标题序号 | 测试通过✅ |
+
+## 1. 页面打开 测试通过✅
+
+两个 URL 都能打开。HTML 页头监测日期对应 2026-09-20,项目为 竞品对比。平台页监测周期为 9月 W38。
+
+
+
+
+
+## 2. 七个 AI 平台 测试通过✅
+
+综合=全平台,通义=通义千问,元宝=腾讯元宝,文心=百度文心;DeepSeek、豆包、Kimi 两边写法相同。
+
+## 3. 露出率、前三率、正面率 测试通过✅
+
+7 个平台相同。综合为 86.2% / 82.2% / 89.1%。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 4. 分平台核心指标 测试通过✅
+
+HTML 各平台 self/趋势最新点对平台 snapshot 分平台三项。综合覆盖六个平台的这三个点。
+
+综合、DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 5. 露出排行 · 各平台明细 测试通过✅
+
+HTML「行业露出率排行榜」对平台「露出排行 · 各平台明细」。只比 Top 10。两边按平均露出率降序取 Top 10。
+
+### 5.1 综合平均露出率对全平台列 测试通过✅
+
+Top 10 同名露出率无差异。
+
+### 5.2 综合 Top 10 名次和品牌名 测试通过✅
+
+| 排名 | HTML 综合 | 平台全平台 |
+|---|---|---|
+| 1 | 卡泰驰 | 卡泰驰 |
+| 2 | 帅车 | 帅车 |
+| 3 | 汽车之家 | 汽车之家 |
+| 4 | 查博士 | 查博士 |
+| 5 | 58同城 | 58同城 |
+| 6 | 车王 | 车王 |
+| 7 | 瓜子二手车 | 瓜子二手车 |
+| 8 | 澳康达 | 澳康达 |
+| 9 | 优信二手车 | 优信二手车 |
+| 10 | 懂车帝 | 懂车帝 |
+
+### 5.3 Top10 品牌分平台露出率 测试通过✅
+
+DeepSeek、豆包、通义、元宝、文心、Kimi:画面上同名占比无差异。
+
+## 6. 正面词、负面词 测试通过✅
+
+文案约定:AI 回答关键词=AI 认知词云;正面关键词=正面词;未监测到负面词=中正面率100%,暂无负面词。
+
+正面词条相同(20 个)。负面词条相同(20 个)。
+
+## 7. 信源内容类型 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 8. 信源发布时间 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 9. 媒体类型前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 10. 媒体名称前 10 测试通过✅
+
+综合:画面上同名占比无差异。
+
+DeepSeek:画面上同名占比无差异。
+
+豆包:画面上同名占比无差异。
+
+通义:画面上同名占比无差异。
+
+元宝:画面上同名占比无差异。
+
+文心:画面上同名占比无差异。
+
+Kimi:画面上同名占比无差异。
+
+## 11. 关联信源标题、渠道、被引次数 测试通过✅
+
+按标题对齐,不比序号。只取前 30。
+
+七个平台:标题集合及渠道、被引次数相同。
+
+## 12. 关联信源标题序号 测试通过✅
+
+比画面序号上的标题。平台按 cite_count 降序稳定排序。
+
+七个平台:前 30 序号标题相同。
+