package crawler import ( "net/url" "regexp" "strings" ) // FilterResult URL 过滤结果 type FilterResult int const ( FilterDiscard FilterResult = iota // 直接丢弃 FilterValid // 确定是导航站 FilterUncertain // 不确定,需 LLM 判断 ) // 黑名单域名 var blacklistDomains = []string{ "t.me", "telegram.me", "twitter.com", "x.com", "facebook.com", "instagram.com", "youtube.com", "google.com", "baidu.com", "weibo.com", "zhihu.com", "github.com", "stackoverflow.com", "wikipedia.org", "amazon.com", "taobao.com", "jd.com", "tmall.com", "qq.com", "163.com", "126.com", "sina.com.cn", "sohu.com", "tencent.com", "alipay.com", "wechat.com", "apple.com", "microsoft.com", "windows.com", "android.com", } // 黑名单扩展名 var blacklistExtensions = []string{ ".apk", ".zip", ".pdf", ".exe", ".dmg", ".ipa", ".rar", ".7z", ".mp4", ".mp3", ".avi", ".jpg", ".png", ".gif", ".svg", ".css", ".js", ".json", ".xml", } // 黑名单路径片段 var blacklistPaths = []string{ "/api/", "/login/", "/logout/", "/register/", "/signup/", "/wp-admin/", "/admin/", "?ref=", "?utm_", "/cdn-cgi/", } // 正向信号 var navSignals = []string{ "nav", "directory", "catalog", "daohang", "dh", "list", "导航", "目录", "聚合", "推荐", "收录", } // RuleFilter 规则引擎过滤 func RuleFilter(rawURL string) FilterResult { u, err := url.Parse(rawURL) if err != nil { return FilterDiscard } host := strings.ToLower(u.Hostname()) path := strings.ToLower(u.Path) fullURL := strings.ToLower(rawURL) // 黑名单域名 for _, d := range blacklistDomains { if strings.Contains(host, d) { return FilterDiscard } } // 黑名单扩展名 for _, ext := range blacklistExtensions { if strings.HasSuffix(path, ext) { return FilterDiscard } } // 黑名单路径 for _, p := range blacklistPaths { if strings.Contains(fullURL, p) { return FilterDiscard } } // 正向信号 for _, sig := range navSignals { if strings.Contains(fullURL, sig) { return FilterValid } } return FilterUncertain } // ExtractDomain 提取域名 func ExtractDomain(rawURL string) string { u, err := url.Parse(rawURL) if err != nil { return "" } return u.Hostname() } var reTGUsernameFromURL = regexp.MustCompile(`t(?:elegram)?\.me/([a-zA-Z][a-zA-Z0-9_]{4,31})`) // ExtractTGUsername 从 URL 提取 TG 用户名 func ExtractTGUsername(rawURL string) string { m := reTGUsernameFromURL.FindStringSubmatch(rawURL) if len(m) > 1 { return m[1] } return "" }