使用正则表达式从URL中提取顶级域名和次级域名

19
我该如何使用正则表达式从URL中提取仅顶级域名和二级域名?我想跳过所有较低级别的域名。有什么想法吗?
9个回答

19

这是我的想法,

使用$锚点从行末开始匹配不是点的任意三个字符。

为了允许类似于.com.au.co.nz类型的域名,字符串末尾的最后一个匹配应该是可选的。

末尾和倒数第二个匹配项都只匹配2-3个字符,以免将其与二级域名混淆。


正则表达式:

[^.]*\.[^.]{2,3}(?:\.[^.]{2,3})?$


演示:

Regex101 示例


顶级域名如“police.uk”或“parliament.uk”等怎么样?更多关于.uk域名的信息在这里:https://en.wikipedia.org/wiki/.uk - LukasMac
这个正则表达式只适用于域名URL,对于完整长度的URL会失败。例如:"www.google.com.bd/abc"将返回"com.bd/abc"。 - priojeet priyom
1
现在,这也将无法适用于任何新的顶级域名,例如.computer或.business。 - brandonscript
由于上述原因被踩了。请使用Publix后缀列表https://publicsuffix.org/。 - ChatGPT
显示剩余2条评论

17

2019年更新

这是一个老问题,随着我们添加新的虚荣顶级域名和更多的国家和地区顶级域名二级域名(例如.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


1
谢谢,这正是我所需要的。 - mel

4
此外,您很可能可以使用类似于以下表达式的方式来完成该操作:
^(?:https?:\/\/)(?:w{3}\.)?.*?([^.\r\n\/]+\.)([^.\r\n\/]+\.[^.\r\n\/]{2,6}(?:\.[^.\r\n\/]{2,6})?).*$

并且添加尽可能多的捕获组,以捕获URL的组件。

演示


如果您希望简化/修改/探索表达式,则已在regex101.com的右上面板上进行了解释。如果您愿意,您还可以在此链接中观看如何匹配一些示例输入。


正则表达式电路图

jex.im可将正则表达式可视化:

enter image description here


1
很遗憾,它与“https://dev59.com/GGEi5IYBdhLWcg3wjc3E”不匹配。 - USauter

3

如果你正在使用 JavaScript 并希望一种简单的方法来提取顶级和二级域名,我最终采用了以下方式:

'example.aus.com'.match(/\.\w{2,3}\b/g).join('')

这个匹配任何以句点开头,后跟两到三个字符,再后面是单词边界

以下是一些示例输出:

'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://或https://开头的URL。 - Davos

0
如果您想要获取所有特定的顶级域名,则可以编写以下正则表达式:
[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


0

由于顶级域现在包括像.wang和.travel这样超过三个字符的内容,这里有一个正则表达式可以满足这些新TLD:

([^.\s]+\.[^.\s]+)$

策略:从字符串的末尾开始,查找一个或多个不是句点或空白字符的字符,后跟一个句点,接着是一个或多个不是句点或空白字符的字符。

http://regexr.com/3bmb3


很遗憾,它不能在像https://www.google.co.uk/这样的两部分顶级域名上使用。 - Garrulinae

0
使用捕获组,你可以实现一些魔法。
例如,考虑以下 JavaScript 代码:

let hostname = 'test.something.else.be';
let domain = hostname.replace(/^.+\.([^\.]+\.[^\.]+)$/, '$1');

document.write(domain);

这将导致一个包含'else.com'的字符串。这是因为正则表达式本身将匹配完整的字符串,并且捕获组将映射到$1。因此,它用'$1'(实际上是'else.com')替换了完整的字符串'test.something.else.com'

这个正则表达式并不漂亮,可能可以通过使用像{3}这样的东西来定义你想要查找子域的深度,但这只是一个示例。


0
以下正则表达式匹配从URL或域名字符串中提取根域和顶级域的域名(命名捕获组):
(?:\w+:\/{2})?(?<cs_domain>(?<cs_domain_sub>(?:[\w\-]+\.)*?)(?<cs_domain_root>[\w\-]+(?<cs_domain_tld>(?:\.\w{2})?(?:\.\w{2,3}|\.xn-+\w+|\.site|\.club))))\|

很难说它是否完美,但它可以在我测试的所有数据集上运行,包括.club、.xn-1234、.co.uk和其他奇怪的结尾。而且它只需要5556步就能处理40k个字符的日志,因此效率似乎也是合理的。


-3

引用了一篇非常古老的文章(撰写时已有10年历史)。现在已经有数十个顶级域名。这可能会让读者误以为这是一个完整的列表。 - Digs
@Digs 你说得对,我还在寻找完整的顶级域名列表。 - Dorian
1
随着新的通用顶级域名不断推出,这几乎是一项不可能完成的任务。 .christmas、.london、.bar、.bank?请参见https://newgtlds.icann.org/en/announcements-and-media/case-studies。最好使用其他答案中提到的正则表达式之一(例如:`\.[a-z]{2,3}(\.[a-z]{2,3})?`)。 - Digs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接