179 行
9.3 KiB
Python
179 行
9.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
中华人民共和国广告法文案合规自动化专项测试
|
||
(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, 'r', 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, "不得使用'国家级科技创新认定'违规表述")
|
||
# 合规的表达应当为官方备案机构或高新技术企业全称
|
||
self.assertIn('全国高新技术企业认定管理机构备案认定', self.contents['single_pc'],
|
||
"资质表述须符合法定规范,应使用全国高新技术企业认定管理机构备案认定")
|
||
|
||
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, 'r', 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()
|
||
|