文件
nahaichuan/tests/test_ad_law_compliance.py

179 行
9.4 KiB
Python

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

"""
中华人民共和国广告法文案合规自动化专项测试
(Ad Law Compliance Test Suite)
严格依据《中华人民共和国广告法》第4条、第8条、第9条、第11条、第28条:
1. 绝对化极限词禁止(第九条第(三)项):最高、最佳、第一、顶级、极致、极速、独家、独创、行业领先等。
2. 国家机关名义与国家级禁用(第九条第(二)、(三)项):严禁使用“国家级认定/国家级项目”等违法定性。
3. 绝对化与夸大承诺禁止(第四条、第二十八条):严禁使用“彻底解决”、“彻底杜绝”、“100%准确”等绝对化承诺。
4. 认证资质与引证规范(第八条、第十一条):规范使用法定全称,杜绝无依据的“权威资质”自我标榜。
"""
import os
import re
import unittest
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
class TestAdLawCompliance(unittest.TestCase):
def setUp(self):
self.target_files = {
'index_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_home/index.html'),
'index_m': os.path.join(ROOT_DIR, 'addons/official/view/web/official_home/index_e.html'),
'single_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_home/single.html'),
'single_m': os.path.join(ROOT_DIR, 'addons/official/view/web/official_home/single_e.html'),
'service_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_product/service_page.html'),
'product_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_product/product_page.html'),
'case_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_case_show/list.html'),
'case_m': os.path.join(ROOT_DIR, 'addons/official/view/web/official_case_show/list_e.html'),
'contact_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_online_message/list.html'),
'nav_pc': os.path.join(ROOT_DIR, 'addons/official/view/web/official_common/pc/nav.html'),
}
self.contents = {}
for key, path in self.target_files.items():
if os.path.exists(path):
with open(path, encoding='utf-8') as f:
self.contents[key] = f.read()
else:
self.contents[key] = ""
# 合并所有页面文本
self.all_text = "\n".join(self.contents.values())
def test_no_extreme_words_ban(self):
"""广告法第九条第(三)项:严禁使用绝对化极限用词"""
extreme_words = [
'极致', '极速', '顶级', '首选', '独家', '独创', '行业领先',
'首屈一指', '绝无仅有', '世界级', '第一品牌', '遥遥领先'
]
for word in extreme_words:
self.assertNotIn(word, self.all_text, f"文案中严禁出现广告法违禁极限词: '{word}'")
def test_no_illegal_national_level_claims(self):
"""广告法第九条第(二)、(三)项:严禁非法使用'国家级'修饰语"""
# 严禁出现“国家级认定”、“国家级自主研发”等违法表述
self.assertNotIn('国家级自主研发', self.all_text, "不得使用'国家级自主研发'违规修饰")
self.assertNotIn('国家级科技创新认定', self.all_text, "不得使用'国家级科技创新认定'违规表述")
# 合规的表达应当使用法定全称,并以有效资料与证书为准
for page_name, content in (('PC 关于我们页', self.contents['single_pc']), ('移动端关于我们页', self.contents['single_m'])):
self.assertIn('计算机软件著作权', content, f"{page_name}资质表述应使用法定全称")
self.assertIn('以有效证书为准', content, f"{page_name}资质表述应以有效证书为准")
def test_no_absolute_guarantee_and_exaggeration(self):
"""广告法第四条/第二十八条:严禁绝对化与夸大免责承诺"""
# 严禁“彻底杜绝”、“彻底解决”、“彻底消除”
absolute_promises = ['彻底解决', '彻底杜绝', '彻底消除', '永不宕机', '零故障', '零风险']
for p in absolute_promises:
self.assertNotIn(p, self.all_text, f"文案中不得出现绝对化夸大承诺: '{p}'")
def test_no_absolute_percentage_guarantees(self):
"""广告法合规:服务与指标承诺中杜绝'100%'绝对化宣传"""
# 过滤 CSS 中的技术属性后,文案内容不应包含绝对化的 100% 承诺
clean_text = re.sub(r'[\'\"a-zA-Z0-9_\-:]*\s*:\s*100%', '', self.all_text)
clean_text = re.sub(r'width\s*=\s*[\'\"]100%[\'\"]', '', clean_text)
clean_text = re.sub(r'height\s*=\s*[\'\"]100%[\'\"]', '', clean_text)
self.assertNotIn('准确率: <strong>100%</strong>', clean_text, "分账准确率不得夸大承诺100%")
self.assertNotIn('自动对账率: <strong>100%</strong>', clean_text, "对账率不得夸大承诺100%")
self.assertNotIn('100% 完整源码', clean_text, "应表述为完整工程源码交付,避免100%绝对词")
self.assertNotIn('100% 客户独占', clean_text, "应表述为客户专属独占")
self.assertNotIn('100% 覆盖', clean_text, "应表述为核心用例全覆盖")
self.assertNotIn('资产 100% 移交', clean_text, "应表述为全套数字资产合规移交")
def test_certifications_pragmatic_framing(self):
"""资质宣传客观严谨,杜绝主观自我标榜'权威资质'"""
self.assertNotIn('权威资质背书', self.contents['single_pc'], "应替换为客观严谨的'法定资质认证'")
self.assertNotIn('权威资质与软著', self.contents['single_m'], "移动端应同步规范为法定资质与合规资产")
def test_forbid_fake_certificates_and_exaggerated_quantities(self):
"""反不正当竞争法与广告法第8条、第28条:严禁捏造虚构证书编号、软著号与虚假数量"""
fake_patterns = [
'黔RQ-2023-0142',
'00123Q31890R1M',
'00123I20982R0S',
'2023SR',
'50+ 项国家软著',
'50+ 软著资产',
'100 多家实体商户',
'100 家实体商户',
'300 多家连锁门店',
'300+ 稳定部署门店',
'300+ 门店稳定运行',
'10W+ 单日交易',
'100,000+ 单/天',
'10W+ 日峰值单量',
'10W+ 日峰值订单',
'日均处理订单 10W+ 单',
'10W+ 单/天',
'99.99% 高可用',
'金融级高可用 99.99%',
'0 风险'
]
for pattern in fake_patterns:
self.assertNotIn(pattern, self.all_text, f"页面中不得出现虚构/编造或无实证支撑的数据与编号: '{pattern}'")
def test_forbid_unsubstantiated_performance_percentages_and_numbers(self):
"""广告法第11条:引证内容必须真实合法,严禁无实证出处的编造成效百分比"""
unsubstantiated_metrics = [
'65% 时效提升',
'70% 结账耗时缩短',
'42% 周转率提升',
'85% 人工消耗降低',
'94.6% 审核采纳准确率',
'94.6% 合规准确率',
'0.02% 差错率降至',
'65% 订单效率提升',
'70% 结算耗时缩短'
]
for metric in unsubstantiated_metrics:
self.assertNotIn(metric, self.all_text, f"页面中严禁无权威依据编造成效百分比: '{metric}'")
def test_svg_showcases_compliance(self):
"""排查 public/assets/addons/official/images/showcases/ 目录下所有原型 SVG 是否包含虚假宣传数据"""
svg_dir = os.path.join(ROOT_DIR, 'public/assets/addons/official/images/showcases')
self.assertTrue(os.path.exists(svg_dir), f"SVG 展示目录不存在: {svg_dir}")
# 针对每个 SVG 定义违规关键词
svg_forbidden_rules = {
'case_distrib.svg': [
'12,890,400', '65%', '3,420', '10W', 'QPS 12,800', '720 天', '0.02%', '全 5 星评价', '零故障'
],
'case_catering.svg': [
'300+', '99.9%', '70%', '零丢单', '28%', '300 家', '3 年', '彻底解决'
],
'case_manufacture.svg': [
'42%', '68%', '2 天', '86%', '92%', '0 误差', '标杆示范项目'
],
'case_gov_agent.svg': [
'80,000+', '94.6%', '0 泄露', '零泄密'
],
'product_mall.svg': [
'389,450', '18.4%', '4,982', '99.8%'
],
'product_erp.svg': [
'142,800', '72%', '周转率提升 42%'
],
'product_saas.svg': [
'99.99%', '34.2%', '42.8%'
],
'service_agent.svg': [
'96.8%', '85%+'
],
'service_middle.svg': [
'12,800', '89.4%'
]
}
for filename, forbidden_list in svg_forbidden_rules.items():
svg_path = os.path.join(svg_dir, filename)
if os.path.exists(svg_path):
with open(svg_path, encoding='utf-8') as f:
content = f.read()
for forbidden in forbidden_list:
self.assertNotIn(forbidden, content, f"SVG 文件 {filename} 中严禁包含虚假宣传或夸大编造数据: '{forbidden}'")
if __name__ == '__main__':
unittest.main()