| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- 美业护肤科普口播 · 敏感词 / 合规机器初筛
- 整合自 content-reviewer 与 medical-content-compliance-auditor 两技能,按美业场景裁剪。
- 输出 markdown 审查报告(风险等级 + 法规依据 + 合规替换 + 结论三选一)。
- 用法:
- python compliance_scan.py --text "口播全文"
- python compliance_scan.py --file path/to/script.md
- python compliance_scan.py --file path/to/script.md --output report.md
- """
- import argparse
- import sys
- from pathlib import Path
- # 词库: (词, 类别, 风险符号, 法规依据, 合规替换)
- WORD_LIST = [
- # 绝对化用语
- ("最好", "绝对化用语", "🟠", "《广告法》第9条", "适合 / 值得考虑"),
- ("最佳", "绝对化用语", "🟠", "《广告法》第9条", "合适"),
- ("第一", "绝对化用语", "🟠", "《广告法》第9条", "代表性 / 较早"),
- ("顶级", "绝对化用语", "🟠", "《广告法》第9条", "优质"),
- ("唯一", "绝对化用语", "🟠", "《广告法》第9条", "特色"),
- ("国家级", "绝对化用语", "🟠", "《广告法》第9条", "(删除)"),
- ("最安全", "绝对化用语", "🟠", "《广告法》第9条", "较安全"),
- ("最有效", "绝对化用语", "🟠", "《广告法》第9条", "较有效"),
- ("全球领先", "绝对化用语", "🟠", "《广告法》第9条", "行业先进"),
- # 治愈承诺
- ("根治", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "改善"),
- ("治愈", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "改善"),
- ("根除", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "减少"),
- ("彻底消除", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "明显缓解"),
- ("永不复发", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "减少反复"),
- ("包治", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "辅助改善"),
- ("治好", "治愈承诺", "🔴", "《广告法》第17条 / 《医疗广告管理办法》", "改善"),
- # 保证性承诺
- ("保证", "保证性承诺", "🟠", "《广告法》第9、25条", "有助于"),
- ("承诺", "保证性承诺", "🟠", "《广告法》第9、25条", "预期(疗效类承诺删除)"),
- ("100%", "保证性承诺", "🟠", "《广告法》第9、25条", "多数情况下"),
- ("无效退款", "保证性承诺", "🟠", "《广告法》第25条", "(删除)"),
- ("签约治疗", "保证性承诺", "🟠", "《广告法》第25条", "(删除)"),
- # 功效夸大·即时
- ("一夜回春", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "逐步改善"),
- ("秒变", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "逐渐"),
- ("瞬间", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "逐渐"),
- ("奇效", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "效果"),
- ("神效", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "效果"),
- ("立竿见影", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "循序渐进、需要坚持"),
- ("立马见效", "功效夸大·即时", "🟡", "《广告法》第28条(虚假宣传)", "逐渐见效"),
- # 医疗功效越界(护肤品禁宣称)
- ("治疗", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "护理 / 改善"),
- ("药用", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "(删除)"),
- ("消炎", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "舒缓"),
- ("杀菌", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "洁净"),
- ("抗炎", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "舒缓"),
- ("抗菌", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "清洁"),
- ("医用", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "(删除)"),
- ("药效", "医疗功效越界", "🟠", "《化妆品监督管理条例》/《广告法》", "(删除)"),
- # 患者证言·对比
- ("术前术后", "患者证言·对比", "🔴", "《医疗广告管理办法》", "(删除,改用示意图)"),
- ("对比图", "患者证言·对比", "🔴", "《医疗广告管理办法》", "(删除,改用示意图)"),
- ("疗效见证", "患者证言·对比", "🔴", "《医疗广告管理办法》", "(删除)"),
- ("患者案例", "患者证言·对比", "🔴", "《医疗广告管理办法》", "(删除 / 脱敏)"),
- # 平台诱导风险
- ("加微信", "平台诱导风险", "🟡", "抖音/小红书审核规则", "进店了解"),
- ("私信我", "平台诱导风险", "🟡", "抖音/小红书审核规则", "(删除)"),
- ("点击下方链接", "平台诱导风险", "🟡", "抖音/小红书审核规则", "(删除)"),
- ("限时优惠", "平台诱导风险", "🟡", "抖音/小红书审核规则", "活动期间优惠"),
- ("最低价", "平台诱导风险", "🟡", "抖音/小红书审核规则", "优惠价"),
- ("免费领", "平台诱导风险", "🟡", "抖音/小红书审核规则", "(删除)"),
- ("扫码", "平台诱导风险", "🟡", "抖音/小红书审核规则", "(删除)"),
- ]
- RISK_RANK = {"🔴": 4, "🟠": 3, "🟡": 2, "🟢": 1}
- CONCLUSION = {
- 4: "不予通过(存在极高违规,必须删除/替换后重检)",
- 3: "修改后通过(高)—— 须替换 🟠 项方可进入生成",
- 2: "修改后通过(中)—— 建议替换 🟡 项",
- 1: "修改后通过(低)—— 建议酌情优化",
- 0: "通过(未检出违禁词)",
- }
- def scan(text: str):
- hits = []
- seen = set()
- for word, cat, risk, law, repl in WORD_LIST:
- if word in text and word not in seen:
- seen.add(word)
- hits.append({
- "word": word, "cat": cat, "risk": risk,
- "law": law, "repl": repl,
- "count": text.count(word),
- })
- hits.sort(key=lambda h: -RISK_RANK[h["risk"]])
- return hits
- def build_report(text: str, hits: list) -> str:
- lines = []
- lines.append("## 敏感词 / 合规检测报告\n")
- lines.append("### 内容类型")
- lines.append("抖音短视频口播文案(美业护肤科普)\n")
- lines.append("### 检测条目")
- if not hits:
- lines.append("\n> ✅ 未检出高危违禁词。\n")
- else:
- lines.append("")
- lines.append("| 违规点 | 原表述 | 风险等级 | 法规依据 | 合规替换 |")
- lines.append("|--------|--------|----------|----------|----------|")
- for h in hits:
- cnt = f"(×{h['count']})" if h["count"] > 1 else ""
- lines.append(
- f"| {h['cat']} | 「{h['word']}」{cnt} | {h['risk']} {('极高' if h['risk']=='🔴' else '高' if h['risk']=='🟠' else '中' if h['risk']=='🟡' else '低')} | {h['law']} | {h['repl']} |"
- )
- lines.append("")
- max_rank = max((RISK_RANK[h["risk"]] for h in hits), default=0)
- lines.append("### 审查结论")
- lines.append(CONCLUSION[max_rank] + "\n")
- if hits:
- lines.append("### 建议")
- for i, h in enumerate(hits, 1):
- lines.append(f"{i}. 「{h['word']}」({h['cat']})→ 替换为「{h['repl']}」,规避对应风险。")
- lines.append(f"{len(hits)+1}. 修改后建议再跑一次本脚本确认无新增违禁词。")
- return "\n".join(lines)
- def main():
- ap = argparse.ArgumentParser(description="美业口播敏感词/合规机器初筛")
- g = ap.add_mutually_exclusive_group(required=True)
- g.add_argument("--text", help="直接传入口播文本")
- g.add_argument("--file", help="传入文本/脚本文件路径(.txt/.md)")
- ap.add_argument("--output", help="将报告写入该文件(可选)")
- args = ap.parse_args()
- if args.text:
- text = args.text
- else:
- p = Path(args.file)
- if not p.exists():
- print(f"[错误] 文件不存在: {args.file}", file=sys.stderr)
- sys.exit(2)
- text = p.read_text(encoding="utf-8")
- hits = scan(text)
- report = build_report(text, hits)
- print(report)
- if args.output:
- Path(args.output).write_text(report, encoding="utf-8")
- print(f"\n[已写入报告] {args.output}", file=sys.stderr)
- # 退出码:极高/高违规 → 非0,便于流程判断
- max_rank = max((RISK_RANK[h["risk"]] for h in hits), default=0)
- sys.exit(0 if max_rank <= 2 else 1)
- if __name__ == "__main__":
- main()
|