feat(compliance): 落实中华人民共和国广告法合规审查:杜绝绝对化极限词、规整国家高新技术企业备案认定与规范承诺用语
这个提交包含在:
89
tests/check_ad_compliance.py
普通文件
89
tests/check_ad_compliance.py
普通文件
@@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
广告法合规静态检查脚本
|
||||
对照《中华人民共和国广告法》重点审查:
|
||||
1. 绝对化极限用语:最高、最佳、第一、顶级、极致、首选、独家、独创、首屈一指等
|
||||
2. 违规国家级表述:国家级(除国家高新技术企业法定全称外不可乱用国家级)、世界级、国际领先
|
||||
3. 虚假或绝对化承诺:100%(非CSS宽高的绝对承诺)、零风险、零故障、永不宕机等
|
||||
4. 模糊引证/夸大宣称
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# 规则定义: (规则说明, 危险正则, 白名单正则或上下文判断函数)
|
||||
RULES = [
|
||||
(
|
||||
"极限词(最系列)",
|
||||
re.compile(r"(最[高佳强优新具权快低大美多全先进顶好])"),
|
||||
lambda text, m: False # 严格禁止
|
||||
),
|
||||
(
|
||||
"极限词(顶级/极系列)",
|
||||
re.compile(r"(顶级|极致|极品|鼎级|极速)"),
|
||||
lambda text, m: False
|
||||
),
|
||||
(
|
||||
"极限词(第一/首系列)",
|
||||
re.compile(r"(第一|No\.1|首[选个家]|首屈一指)"),
|
||||
lambda text, m: False
|
||||
),
|
||||
(
|
||||
"绝对化用词(独家/独创/唯一)",
|
||||
re.compile(r"(独家|独创|唯一|绝无仅有)"),
|
||||
lambda text, m: False
|
||||
),
|
||||
(
|
||||
"绝对化承诺(100%/零故障/零风险)",
|
||||
re.compile(r"(100%|零故障|零风险|零瑕疵|包过|永久免费)"),
|
||||
lambda text, m: "width" in text.lower() or "height" in text.lower() or "size" in text.lower()
|
||||
),
|
||||
(
|
||||
"违规国家级表述",
|
||||
re.compile(r"(国家级(?!高新技术企业)|世界级|国际领先)"),
|
||||
lambda text, m: False
|
||||
),
|
||||
]
|
||||
|
||||
def scan_files(directory):
|
||||
violations = []
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for f in files:
|
||||
if not f.endswith(('.html', '.php', '.js')):
|
||||
continue
|
||||
path = os.path.join(root, f)
|
||||
with open(path, 'r', encoding='utf-8', errors='ignore') as fp:
|
||||
for line_no, line in enumerate(fp, 1):
|
||||
# 过滤 CSS 中的技术百分比
|
||||
filtered_line = re.sub(r'[\'\"a-zA-Z0-9_\-:]*\s*:\s*100%', '', line)
|
||||
filtered_line = re.sub(r'width\s*=\s*[\'\"]100%[\'\"]', '', filtered_line)
|
||||
filtered_line = re.sub(r'height\s*=\s*[\'\"]100%[\'\"]', '', filtered_line)
|
||||
|
||||
for rule_name, pattern, allow_fn in RULES:
|
||||
for match in pattern.finditer(filtered_line):
|
||||
matched_text = match.group(0)
|
||||
if not allow_fn(line, match):
|
||||
violations.append({
|
||||
'file': path,
|
||||
'line_no': line_no,
|
||||
'rule': rule_name,
|
||||
'matched': matched_text,
|
||||
'snippet': line.strip()
|
||||
})
|
||||
return violations
|
||||
|
||||
if __name__ == '__main__':
|
||||
target_dir = sys.argv[1] if len(sys.argv) > 1 else 'addons/official/view/web'
|
||||
results = scan_files(target_dir)
|
||||
report_path = 'tests/ad_audit_report.txt'
|
||||
with open(report_path, 'w', encoding='utf-8') as f:
|
||||
f.write(f"=== 中华人民共和国广告法合规审查清单 (扫描目录: {target_dir}) ===\n")
|
||||
f.write(f"共排查潜在风险点: {len(results)} 处\n\n")
|
||||
for r in results:
|
||||
f.write(f"【{r['rule']}】 文件: {r['file']} 第 {r['line_no']} 行\n")
|
||||
f.write(f" 敏感/违规词: {r['matched']}\n")
|
||||
f.write(f" 上下文原句: {r['snippet']}\n")
|
||||
f.write("-" * 60 + "\n")
|
||||
print(f"审查完成!已生成报告: {report_path},发现风险项: {len(results)} 处")
|
||||
|
||||
在新工单中引用
屏蔽一个用户