diff --git a/db/company_scope.go b/db/company_scope.go index 236afa3..8fb8c08 100644 --- a/db/company_scope.go +++ b/db/company_scope.go @@ -152,8 +152,12 @@ func ParseAutoScopeLine(line string) (ParsedScope, error) { if looksLikeDomain { return ParseScopeLine(raw) } + // 备案号本身不含点号(如 京ICP备12345678号-1)。带点的文本多半掺了域名或版本号, + // 按 ICP 存下来只会得到一条永远匹配不上任何资产的死规则 —— ICP 归属走的是精确 + // 相等比较(见 companies.go 的 kind='icp' 归属查询),所以这类文本归为关键词。 lower := strings.ToLower(raw) - if strings.Contains(lower, "icp") || strings.Contains(raw, "备案") { + if !strings.ContainsAny(raw, "..。") && + (strings.Contains(lower, "icp") || strings.Contains(raw, "备案")) { return ParseScopeInput(ScopeInput{Kind: "icp", Value: raw}) } return ParseScopeInput(ScopeInput{Kind: "keyword", Value: raw}) diff --git a/db/company_scope_test.go b/db/company_scope_test.go index f1be837..713938e 100644 --- a/db/company_scope_test.go +++ b/db/company_scope_test.go @@ -60,6 +60,11 @@ func TestParseAutoScopeLine(t *testing.T) { {name: "icp chinese", input: "沪网备案 9988", kind: "icp", normalized: "沪网备案9988"}, {name: "icp domain", input: "icp.example.com", kind: "domain", normalized: "icp.example.com"}, {name: "icp url query", input: "https://example.com/path?icp=1", kind: "domain", normalized: "example.com"}, + // 备案号不含点号:掺了域名/版本号的描述性文字归关键词,否则会存成一条 + // 永远匹配不上的死 ICP 规则。 + {name: "icp with domain text", input: "备案 www.example.com", kind: "keyword", normalized: "备案 www.example.com"}, + {name: "icp with version text", input: "某公司 ICP v1.0", kind: "keyword", normalized: "某公司 icp v1.0"}, + {name: "icp fullwidth dot", input: "备案 例.com", kind: "keyword", normalized: "备案 例.com"}, {name: "keyword", input: " ACME Security ", kind: "keyword", normalized: "acme security"}, {name: "colon keyword", input: "ACME: Cloud: Security", kind: "keyword", normalized: "acme: cloud: security"}, {name: "empty", input: " ", wantErr: true},