【问题标题】:Extracting top-level and second-level domain from a URL using regex使用正则表达式从 URL 中提取顶级域和二级域
【发布时间】:2014-02-06 01:34:11
【问题描述】:

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

【问题讨论】:

    标签: regex url dns


    【解决方案1】:

    以下正则表达式将域与来自 url 或域字符串的 root 和 tld 提取(命名的捕获组)匹配:

    (?:\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 和其他奇怪的结尾。它针对 40k 字符的日志以 5556 步完成,因此效率似乎也很合理。

    【讨论】:

      【解决方案2】:

      对于任何使用 JavaScript 并想要一种简单的方法来提取顶级域和二级域的人,我最终这样做了:

      'example.aus.com'.match(/\.\w{2,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?:\/\/)(?:w{3}\.)?.*?([^.\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”
              猜你喜欢
              • 2018-01-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多