81 lines
3.2 KiB
Python
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)})
|