Files
tg-spam-guard/import_adblock_rules.py
2026-07-07 19:00:06 +08:00

81 lines
3.2 KiB
Python

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)})