JS正则提取URL主域名时多级子域识别错误,求正确正则或替代方案
解决方案
问题原因
现有代码的核心问题是提取到hostname后直接按.拆分取第一个元素,完全没有区分「子域名前缀」、「主域名」、「顶级/多级公共后缀」,遇到多级子域名的场景(比如shop.store.com)就会误把前面的子域名当成主域名返回。
方案1:轻量正则适配(覆盖你给出的所有测试场景)
不需要额外依赖,适配你列出的所有测试用例,支持1-2级公共后缀(比如com、com.tr都可正常识别):
function getMainDomain(url) { // 第一步先过滤协议、端口、路径等内容,提取纯hostname const hostname = url.replace(/^(?:https?:\/\/)?/i, '').split(/[/:?#]/)[0]; // 匹配主域名:自动跳过www前缀、任意单级子域名前缀,忽略后面的公共后缀 const match = hostname.match(/^(?:www\d?\.|[a-z0-9-]+\.)?([a-z0-9-]+)(?:\.[a-z]{2,}){1,2}$/i); return match ? match[1] : null; }
测试结果完全符合预期:
getMainDomain('www.google.com')→ googlegetMainDomain('en.store.com')→ storegetMainDomain('google.com')→ googlegetMainDomain('www2.site.com')→ sitegetMainDomain('www.google.com.tr')→ googlegetMainDomain('https://www.google.com.tr')→ googlegetMainDomain('https://google.com.tr')→ googlegetMainDomain('shop.store.com')→ store
方案2:通用精准方案(适配所有公共后缀场景)
如果需要处理更复杂的公共后缀(比如co.uk、gov.cn这类多级后缀,或者自定义后缀),可以基于公共后缀规则实现,可扩展性更高:
// 常用公共后缀列表,可根据业务需求自行扩展 const publicSuffixes = new Set(['com', 'tr', 'cn', 'uk', 'co.uk', 'com.tr', 'net', 'org', 'io', 'dev']); function getMainDomain(url) { const hostname = url.replace(/^(?:https?:\/\/)?/i, '').split(/[/:?#]/)[0]; const parts = hostname.split('.'); let suffixLength = 0; // 从后往前匹配最长的公共后缀 for (let i = 1; i <= parts.length; i++) { const suffix = parts.slice(-i).join('.'); if (publicSuffixes.has(suffix)) { suffixLength = i; } } // 公共后缀前的最后一段就是目标主域名 if (parts.length > suffixLength) { return parts[parts.length - suffixLength - 1]; } return null; }
内容的提问来源于stack exchange,提问作者tosunkayaG
相关产品推荐
相关产品推荐

