# -*- coding: utf-8 -*- """验证字符串+结构指纹方案的**跨构建一致性** —— 只基于 har/online/ 全新样本。 案例 §5.3 的验收标准: "3 个 tdc.js 版本、37 个模块、全部正确识别,无一 unknown"。 本脚本再进一步:不仅要求"无 unknown",还要求 ① 每份构建内部 37 项都有名字 ② 各构建之间的**语义名集合**一致(说明识别的是同一批采集器) ③ 语义名 -> 每项在 cd 里的**相对位置**可交叉核对 """ import glob import sys from collections import Counter from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "tools")) import tdc_modules as tm # noqa: E402 BATCH = sorted(glob.glob(str(ROOT / "har" / "online" / "*" / "tdc_*.js"))) print("全新在线样本 %d 份(只使用这批数据)" % len(BATCH)) print() results = {} for f in BATCH: rows = tm.analyze(f) names = [r["name"] for r in rows] results[f] = rows unk = sum(1 for n in names if n == "unknown") via_struct = sum(1 for r in rows if r.get("via_struct")) via_deleg = sum(1 for r in rows if r.get("via_delegate")) print(" %-24s 项%2d unknown %d | 字符串直判 %2d 委派链 %d 结构兜底 %d" % (f.split("/")[-1], len(rows), unk, len(rows) - via_struct - via_deleg, via_deleg, via_struct)) print() keys = list(results) base = Counter(r["name"] for r in results[keys[0]]) print("以 %s 为基准:%d 个语义名(去重 %d)" % (keys[0].split("/")[-1], len(base), len(set(base)))) print() for f in keys[1:]: c = Counter(r["name"] for r in results[f]) same = sum((base & c).values()) only_base = sum((base - c).values()) only_it = sum((c - base).values()) print(" vs %-22s 相同 %2d | 仅基准有 %2d | 仅有它有 %2d" % (f.split("/")[-1], same, only_base, only_it)) print() common = set(base) for f in keys[1:]: common &= set(Counter(r["name"] for r in results[f])) allnames = set() for f in keys: allnames |= set(r["name"] for r in results[f]) print(">>> 所有构建**共同**识别出的语义名: %d 个" % len(common)) print(">>> 出现过的语义名总数 : %d 个" % len(allnames)) print(">>> 差异名:", sorted(allnames - common) if allnames - common else "无(完全一致)") print() # 唯一性检查:单构建内是否有重名(重名 = 锚点有歧义) print("单构建内重名检查(重名说明该锚点有歧义):") for f in keys: c = Counter(r["name"] for r in results[f]) dup = {k: v for k, v in c.items() if v > 1} print(" %-24s 重名 %d 组 %s" % (f.split("/")[-1], len(dup), dict(sorted(dup.items()))))