使用正则表达式从 URL 中提取***域和二级域
Posted
技术标签:
【中文标题】使用正则表达式从 URL 中提取***域和二级域【英文标题】:Extracting top-level and second-level domain from a URL using regex 【发布时间】:2014-02-06 01:34:11 【问题描述】:如何使用正则表达式从 URL 中仅提取***域和二级域?我想跳过所有较低级别的域。有什么想法吗?
【问题讨论】:
【参考方案1】:以下正则表达式将域与来自 url 或域字符串的 root 和 tld 提取(命名的捕获组)匹配:
(?:\w+:\/2)?(?<cs_domain>(?<cs_domain_sub>(?:[\w\-]+\.)*?)(?<cs_domain_root>[\w\-]+(?<cs_domain_tld>(?:\.\w2)?(?:\.\w2,3|\.xn-+\w+|\.site|\.club))))\|
很难说它是否完美,但它适用于我反对的所有测试数据集,包括 .club、.xn-1234、.co.uk 和其他奇怪的结尾。它针对 40k 字符的日志以 5556 步完成,因此效率似乎也很合理。
【讨论】:
【参考方案2】:对于任何使用 javascript 并想要一种简单的方法来提取***域和二级域的人,我最终这样做了:
'example.aus.com'.match(/\.\w2,3\b/g).join('')
这匹配任何带有句点后跟两个或三个字符,然后是word boundary的内容。
以下是一些示例输出:
'example.aus.com' // .aus.com
'example.austin.com' // .austin.com
'example.aus.com/howdy' // .aus.com
'example.co.uk/howdy' // .co.uk
有些人可能需要一些更聪明的东西,但这对我的特定数据集来说已经足够了。
编辑
我意识到实际上有不少二级域的长度超过 3 个字符(并且允许)。因此,再次为简单起见,我只是删除了正则表达式的字符计数元素:
'example.aus.com'.match(/\.\w*\b/g).join('')
【讨论】:
OP 要求排除任何较低级别的域,例如lowerlevel.domain.co.uk 使用您的示例给出“.domain.co.uk”。也不处理以 http:// 或 http:// 开头的 URL【参考方案3】:此外,您也可以使用类似于,
^(?:https?:\/\/)(?:w3\.)?.*?([^.\r\n\/]+\.)([^.\r\n\/]+\.[^.\r\n\/]2,6(?:\.[^.\r\n\/]2,6)?).*$
并添加尽可能多的要捕获 URL 组件的捕获组。
Demo
如果您希望简化/修改/探索表达式,在regex101.com 的右上角面板中已对此进行了说明。如果您愿意,您还可以在this link 中观看它如何与一些示例输入匹配。
正则表达式电路
jex.im 可视化正则表达式:
【讨论】:
【参考方案4】:2019 年更新
这是一个老问题,随着我们开始添加新的虚名 TLD 和更多 ccTLD 二级域(例如.co.uk
、.org.uk
),这里的挑战变得更加复杂。如此之多,以至于几乎可以保证正则表达式返回误报或误报。
可靠地获取主要主机的唯一方法是调用了解它们的服务,例如Public Suffix List。
您可以使用几个开源库,例如 psl,或者您可以编写自己的。
psl
的用法非常直观。从他们的文档中:
var psl = require('psl');
// Parse domain without subdomain
var parsed = psl.parse('google.com');
console.log(parsed.tld); // 'com'
console.log(parsed.sld); // 'google'
console.log(parsed.domain); // 'google.com'
console.log(parsed.subdomain); // null
// Parse domain with subdomain
var parsed = psl.parse('www.google.com');
console.log(parsed.tld); // 'com'
console.log(parsed.sld); // 'google'
console.log(parsed.domain); // 'google.com'
console.log(parsed.subdomain); // 'www'
// Parse domain with nested subdomains
var parsed = psl.parse('a.b.c.d.foo.com');
console.log(parsed.tld); // 'com'
console.log(parsed.sld); // 'foo'
console.log(parsed.domain); // 'foo.com'
console.log(parsed.subdomain); // 'a.b.c.d'
旧答案
你可以用这个:
(\w+\.\w+)$
如果没有更多细节(示例文件、您使用的语言),很难准确判断这是否可行。
例如:http://regex101.com/r/wD8eP2
【讨论】:
谢谢,这正是我需要的。【参考方案5】:如果你想要所有特定的***域名,那么你可以这样写正则表达式:
[RegularExpression("^(https?:\\/\\/)?(([\\w]+)?\\.?(\\w+\\.((za|zappos|zara|zero|zip|zippo|zm|zone|zuerich|zw))))\\/?$", ErrorMessage = "Is not a valid fully-qualified URL.")]
您也可以从此链接添加更多域名:
https://www.icann.org/resources/pages/tlds-2012-02-25-en
【讨论】:
【参考方案6】:通过捕获组,您可以实现一些魔法。
例如,考虑以下 javascript:
let hostname = 'test.something.else.be';
let domain = hostname.replace(/^.+\.([^\.]+\.[^\.]+)$/, '$1');
document.write(domain);
这将产生一个包含'else.com'
的字符串。这是因为正则表达式本身将匹配完整的字符串,并且捕获组将映射到$1
。所以它将完整的字符串'test.something.else.com'
替换为'$1'
,实际上是'else.com'
。
正则表达式并不漂亮,可能可以通过 3
之类的东西变得更加动态,用于定义要查找子域的深度,但这只是一个示例。
【讨论】:
【参考方案7】:如果您需要更具体:
/\.(?:nl|se|no|es|milru|fr|es|uk|ca|de|jp|au|us|ch|it|io|org|com|net|int|edu|mil|arpa)/
基于http://www.seobythesea.com/2006/01/googles-most-popular-and-least-popular-top-level-domains/
【讨论】:
引用了一篇非常古老的文章(撰写本文时已有 10 年历史)。现在还有几十个***域名。这可能会误导读者认为这是一个完整的列表 @Digs 你说得对,我还在寻找完整的***域名列表 随着新的通用***域名不断出现,这几乎是一项不可能完成的任务。 .christmas、.london、.bar、.bank?请参阅newgtlds.icann.org/en/announcements-and-media/case-studies 可能最好使用其他答案中提到的正则表达式之一(例如:\.[a-z]2,3(\.[a-z]2,3)?
)【参考方案8】:
由于 TLD 现在包含超过三个字符的内容,例如 .wang 和 .travel,因此这里有一个满足这些新 TLD 的正则表达式:
([^.\s]+\.[^.\s]+)$
策略:从字符串的末尾开始,查找一个或多个不是句点或空格的字符,然后是一个句点,然后是一个或多个不是句点或空格的字符。
http://regexr.com/3bmb3
【讨论】:
【参考方案9】:这是我的想法,
使用$
锚点从行尾开始匹配任何不是点的内容,重复三次。
字符串末尾的最后一个匹配项应该是可选的,以允许.com.au
或.co.nz
类型的域。
最后一个和倒数第二个匹配都只会匹配2-3个字符,这样就不会和二级域名混淆了。
正则表达式:
[^.]*\.[^.]2,3(?:\.[^.]2,3)?$
演示:
Regex101 Example
【讨论】:
“police.uk”或“parliament.uk”等***域怎么样?更多关于.uk域的信息在这里:en.wikipedia.org/wiki/.uk 此正则表达式仅适用于域 url,而对于全长 url 则失败。例如:“www.google.com.bd/abc”将返回“com.bd/abc” 现在对于任何新的***域名(如 .computer 或 .business)也将失败。 这也不适用于 3 个字母的域名,例如 www.rgj.com 或 account.app.com... 域区域可能超过3个字母,即“.agency”以上是关于使用正则表达式从 URL 中提取***域和二级域的主要内容,如果未能解决你的问题,请参考以下文章