使用正则表达式从 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 中提取***域和二级域的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式仅提取 url 的域和子域

如何使用正则表达式从字符串中提取第 n 个 URL?

使用正则表达式从 url 中提取参数值

使用正则表达式从 url 中提取参数值

使用 Java + 正则表达式从文本文档中提取 URL

正则表达式使用 Python 从 HTML 中的 href 属性中提取 URL [重复]