【问题标题】:Get second level domain name from URL从 URL 获取二级域名
【发布时间】:2014-11-14 13:23:43
【问题描述】:

有没有办法从url获取顶级域名

例如,“https://images.google.com/blah” => “google”

我发现了这个:

var domain = new URL(pageUrl).hostname; 

但它给了我“images.google.com”而不仅仅是谷歌。

我的单元测试是:

https://images.google.com   => google
https://www.google.com/blah => google
https://www.google.co.uk/blah => google
https://www.images.google.com/blah => google

【问题讨论】:

  • 顶级域实际上是 .com 部分,所以我认为您可能正在寻找二级域。但是,您希望从 video.google.co.uk 之类的内容中得到什么回报——“co”(二级域)或“google”或“google.co”?
  • 只是“google”我在问题中提到过
  • 我虽然在你的情况下真正的顶级域实际上是 com,但 google 是它的子域?

标签: javascript url subdomain url-parsing


【解决方案1】:

我只是想添加一些东西,因为这个是在谷歌之上的,我正在搜索它。

您可以下载所有 url 的维基百科数据集(33Mb 下载)并将其用作您的测试用例的测试集。另一个测试来源是 Alexa 排名前 1.000.000 的网站和/或一些流行博客的下载并从中解析出 url。

首先,我将其范围限定为检索某个“对象”的唯一 URI。因为每个 html 页面原则上都可以有另一个 favicon 来指向通常代表对象。 “那是所有者的域”。我还将其范围限定为 Alexa 前 10.000.000 个站点。并且您使用 Google Favicon 服务验证这与您自己的算法匹配的程度,例如接收网站图标,看看它们是否相同。

  • 首先你需要了解顶级域名官方。这些在这里:https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
  • 单击每个条目会给出官方子域/后缀(单击维基百科页面中的第一列)。这些也需要 放在你的数组中。因为所有“注册”域的东西都是 不是从中获取网站图标的域。有最奇怪的 那里的组合,并不是所有的都那么清楚,例如那些 编号为(例如https://en.wikipedia.org/wiki/.bg),但 那些基于工作类型的官方......更模糊。所有这些都是 数组中的键。因为首先你正在寻找 这背后的第一句话。那是某人拥有并需要的东西 favicon 来表示它。 Mozilla 维护了一个列表,但你 将不得不附加它。这个项目https://github.com/lupomontero/psl 可能会有所帮助(基于https://publicsuffix.org/)但是我在测试期间注意到它并没有涵盖所有情况。
  • 还有“非官方”域名注册,例如facebook 游戏位于 /facebook.com/xxs 下,并有自己的图标。所以你需要把它也放在数组中,这样你就可以找到这些 uri 的唯一图标。在 Alexa 热门点击中,有相当多的条目不是主域,而是访问量最大的 /user/john(并且有另一个图标)。在 Alexa 中将范围限定为前 10.000.000 有助于将其范围限定为仅最流行的内容。
  • 一旦你拥有了这个数组并且你的测试集与你的匹配率达到了 80%,你就可以专注于上面没有涵盖的用例,例如:各种重定向和更奇怪的东西,比如某些 nginx 服务器,它们提供奇怪的 http 状态,并且可能是由某人自定义修改的等等......
  • 如果您在全球化/本地化应用程序中使用它,需要注意的另一件事是对语言和域具有相同的概念引用,例如wikipedia.en 和 wikipedia.nl。在这种情况下,指向同一概念的“您点击的链接”必须考虑到较大门户中存在的这些属性。
  • 那么缺少的是例如abcd.com 有 defgh.abcd.com 和 news.abcd.com,其中 defgh.abcd.com 是完全不同的东西,或者更糟糕的是重定向到完全不同的公司,你需要添加一些技巧,例如检查元数据或图标以确保这仍然是主域的一部分或完全不同的东西。

这是一项相当多的工作,而且还要保持更新。我的建议是不要从简单的案例开始,例如https://en.wikipedia.org/wiki/.tj 但首先是困难的,例如https://en.wikipedia.org/wiki/.br。您需要将其设为字典/数组,因为“.uk”和“.gov.uk”是不同的键。

【讨论】:

    【解决方案2】:

    这是我对解决问题的天真看法。

    url.split('.').reverse()[1].split('//').reverse()[0]
    

    支持子域,但不支持公共后缀 SLD。

    【讨论】:

      【解决方案3】:

      这是除了维护黑白顶级域列表之外最简单的解决方案。

      1. 如果顶级域有两个或更多字符“xxxx.yyy”,则匹配顶级域

      2. 匹配顶级域和子域,如果两者都在两个字符'xxxxx.yy.zz'下

      3. 删除匹配。

      4. 返回最后一个句点和字符串结尾之间的所有内容。


      我把它分成两个独立的 OR|regex 规则:

      1. (\.[^\.]*)(\.*$) - 如果顶级域 >= 3,则到字符串结尾的最后一个句点。
      2. (\.[^\.]{0,2})(\.[^\.]{0,2})(\.*$) - 顶级域和子域

      var regex_var = new RegExp(/(\.[^\.]{0,2})(\.[^\.]{0,2})(\.*$)|(\.[^\.]*)(\.*$)/);
      var unit_test = 'xxx.yy.zz.'.replace(regex_var, '').split('.').pop();
      document.write("Returned user entered domain: " + unit_test + "\n");
      
      var result = location.hostname.replace(regex_var, '').split('.').pop();
      document.write("Current Domain: " + result);

      【讨论】:

      • 感谢您解决第二个问题! :) 这是我制作的一个书签,用于复制 Markdown 格式的 URL,末尾带有域名:javascript:if(typeof%20WxXYnC60==typeof%20alert)WxXYnC60();window.prompt("Copy%20page%20title%20and%20URL","["+document.title+"]("+location.href+")%20("+location.hostname.replace(new%20RegExp(/(\.[^\.]{2})(\.[^\.]{2})(\.*$)|(\.[^\.]*)(\.*$)/),'').split('.').pop()+")");void(0);
      • @Null 此正则表达式是否也适用于国际化 ccTLD en.wikipedia.org/wiki/…
      • 虽然我没有使用过国际编码域,但只要有相同的句点结构来分隔顶级域,它就可以工作。
      【解决方案4】:
      function getDomainName( hostname ) {
          var TLDs = new RegExp(/\.(com|net|org|biz|ltd|plc|edu|mil|asn|adm|adv|arq|art|bio|cng|cnt|ecn|eng|esp|etc|eti|fot|fst|g12|ind|inf|jor|lel|med|nom|ntr|odo|ppg|pro|psc|psi|rec|slg|tmp|tur|vet|zlg|asso|presse|k12|gov|muni|ernet|res|store|firm|arts|info|mobi|maori|iwi|travel|asia|web|tel)(\.[a-z]{2,3})?$|(\.[^\.]{2,3})(\.[^\.]{2,3})$|(\.[^\.]{2})$/);
          return hostname.replace(TLDs, '').split('.').pop();
      }
      
      /*** TEST ***/
      
      var domains = [
          'domain.com',
          'subdomain.domain.com',
          'www.subdomain.domain.com',
          'www.subdomain.domain.info',
          'www.subdomain.domain.info.xx',
          'mail.subdomain.domain.co.uk',
          'mail.subdomain.domain.xxx.yy',
          'mail.subdomain.domain.xx.yyy',
          'mail.subdomain.domain.xx',
          'domain.xx'
      ];
      
      var result = [];
      for (var i = 0; i < domains.length; i++) {
          result.push( getDomainName( domains[i] ) );
      }
      
      alert ( result.join(' | ') );
      
      // result: domain | domain | domain | domain | domain | domain | domain | domain | domain | domain
      

      【讨论】:

      • 好答案,情况全面。得到的结果基本正确。
      • 这不适用于虚域(例如以 .amsterdam 结尾)
      【解决方案5】:

      您要从 URL 中提取的不是 top-level domain (TLD)。 TLD 是最右边的部分,例如.com。

      话虽如此,但我认为没有一种简单的方法可以做到这一点,因为有些网址有两个“常见”部分,例如“.co.uk”,我想您不想提取“.co” “在那些情况下。您可以使用现有的由两部分组成的“TLD”列表进行检查,以便知道何时提取哪一部分。

      【讨论】:

        【解决方案6】:

        你可以这样做:

        location.hostname.split('.').pop()
        

        编辑

        看到对您的问题的更改,您需要一个所有 TLD 的列表来匹配并从主机名中删除,然后您可以使用 split('.').pop()

        // small example list
        var re = new RegExp('\.+(co.uk|me|com|us)')
        var secondLevelDomain = 'https://www.google.co.uk'.replace(re, '').split('.').pop()
        

        【讨论】:

        • 请注意,为此,您的正则表达式将是页面长,只需检查每个页面的描述页面:en.wikipedia.org/wiki/List_of_Internet_top-level_domains。这也不包括提供托管服务的非官方域名注册商,例如 wordpress.com 和 blogspot.com,其中真实站点位于 / 之后,但所有者将其视为“他的域”。
        【解决方案7】:

        这个怎么样?

        location.hostname.split('.').reverse()[1]

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-10
          • 1970-01-01
          • 1970-01-01
          • 2013-04-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多