from pathlib import Path import re from datetime import datetime SRC = Path('/tmp/adblock_import') OUT = Path('rules/adblock_domains.txt') files = [ SRC / 'easylistchina.txt', SRC / 'gitee_adblock/adblock.txt', SRC / 'gitee_adblock/adblock_lite.txt', SRC / 'gitee_adblock/adblock_plus.txt', SRC / 'gitee_adblock/adblock_privacy.txt', SRC / 'github_adblock/ADBLOCK_RULE_COLLECTION_DOMAIN.txt', SRC / 'github_adblock/ADBLOCK_RULE_COLLECTION_DOMAIN_Lite.txt', ] # 宽松域名提取,后面再过滤明显非域名/静态资源片段 DOMAIN_RE = re.compile(r'(?i)(?:\|\|)?\b([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+)\b') BAD_SUFFIX = {'.js', '.css', '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.ico', '.mp4', '.m3u8', '.json', '.xml', '.php', '.html'} COMMON_ALLOW = { 'github.com','gitee.com','google.com','microsoft.com','apple.com','qq.com','weixin.qq.com','telegram.org', 't.me','youtube.com','bilibili.com','baidu.com','cloudflare.com','jquery.com','vuejs.org','npmjs.com' } def valid_domain(d: str) -> bool: d = d.lower().strip('.-_^*/') if not d or d in COMMON_ALLOW: return False if any(d.endswith(s) for s in BAD_SUFFIX): return False parts = d.split('.') if len(parts) < 2 or any(not p or len(p) > 63 for p in parts): return False tld = parts[-1] if len(tld) < 2 or not re.fullmatch(r'[a-z][a-z0-9-]{1,23}', tld): return False # 排除纯数字/IP if all(p.isdigit() for p in parts): return False return True domains = set() source_counts = {} for path in files: if not path.exists(): continue count_before = len(domains) with path.open('r', encoding='utf-8', errors='ignore') as f: for raw in f: line = raw.strip() if not line or line.startswith(('!', '#', '[')) or line.startswith('@@'): continue # 跳过元素隐藏/CSS 规则 if '##' in line or '#?#' in line or '#@#' in line: continue # 去掉 options,减少误提取 line = line.split('$', 1)[0] for m in DOMAIN_RE.finditer(line): d = m.group(1).lower().strip('.-_^*/') if valid_domain(d): domains.add(d) source_counts[str(path.relative_to(SRC))] = len(domains) - count_before OUT.parent.mkdir(parents=True, exist_ok=True) existing_header = '' if OUT.exists(): backup = OUT.with_suffix(f'.txt.bak-{datetime.now().strftime("%Y%m%d%H%M%S")}') OUT.replace(backup) lines = [ '# Adblock 域名过滤库(自动导入)', '# 来源:gitee.com/uniartisan2018/adblock_list、github.com/REIJI007/Adblock-Rule-Collection、EasyList China', '# 用途:仅当聊天消息中出现 URL/域名时匹配,不作为普通关键词扫描,避免误杀与性能问题。', f'# 更新时间:{datetime.now().isoformat(timespec="seconds")}', f'# 有效域名:{len(domains)}', ] for k, v in source_counts.items(): lines.append(f'# source {k}: +{v}') lines.append('') lines.extend(sorted(domains)) OUT.write_text('\n'.join(lines) + '\n', encoding='utf-8') print({'domains': len(domains), 'sources': source_counts, 'output': str(OUT)})