使用 JavaScript 获取没有子域的域名?

IT技术 javascript
2021-03-16 16:52:15

如何获取没有子域的域名?

例如,如果 url 是“ http://one.two.roothost.co.uk/page.html ”,如何获得“roothost.co.uk”?

6个回答

以下是提取没有任何子域的域名的解决方案。此解决方案不对 URL 格式做出任何假设,因此它应该适用于任何 URL。由于有些域名有一个后缀 ( .com),有些有两个或多个 ( .co.uk),为了在所有情况下都得到准确的结果,我们需要使用Public Suffix List解析主机名,其中包含所有公共域名后缀的列表.


解决方案

首先,在 HTML 的脚本标记中包含公共后缀列表 js api,然后在 JavaScript 中获取可以调用的主机名:

var parsed = psl.parse('one.two.roothost.co.uk');
console.log(parsed.domain);

...这将返回“roothost.co.uk”。要从当前页面获取名称,您可以使用location.hostname代替静态字符串:

var parsed = psl.parse(location.hostname);
console.log(parsed.domain);

最后,如果你需要直接从一个完整的 URL 字符串中解析出一个域名,你可以使用以下方法:

var url = "http://one.two.roothost.co.uk/page.html";
url = url.split("/")[2]; // Get the hostname
var parsed = psl.parse(url); // Parse the domain
document.getElementById("output").textContent = parsed.domain;

JSFiddle 示例(它包括jsFiddle 中的整个缩小库,所以向下滚动!):https ://jsfiddle.net/6aqdbL71/2/

使用user1551066提出的 a.href 提示会不会更强大
2021-04-25 16:52:15
好吧 - 如果它确实定期更新 - 简单地从 CDN 中提取脚本会更简单,而不是求助于自动更新和其他类似的东西。对我来说,这里的主要问题是外部依赖,但我想如果它有效,它就有效。
2021-04-28 16:52:15
值得注意的是,尽管 TLD 在很长一段时间内都相当静态,但它们目前正在发生变化这会稍微混淆你的问题。
2021-05-04 16:52:15
@jedd.ahyoung psl 脚本会定期更新 AFAIK。作为更改 TLD 的解决方案,您可以让脚本按计划从 GitHub 自动更新服务器端。例如,每周您的服务器都会运行一个下载新 psl 脚本的作业,以便它对客户端来说是新鲜的。对于奖励积分,您甚至可以设置一个 git hook 而不是预定的作业。
2021-05-05 16:52:15
这个解决方案对我来说很疯狂。122KB 的压缩代码添加到您的库中,如果您深入研究代码,您会得到非常静态的定义:“hgtv”、“hiphop”、“hisamitsu”、“hitachi”、“hiv”、“hkt”、“hockey”、 "holds","holiday","homedepot","homegoods","homes","homesense","honda"....我很高兴这个解决方案可用,但真的希望子域钓鱼被内置到浏览器中.
2021-05-10 16:52:15

我创建了这个使用URL解析的函数它通过假设所有主机名将具有 4 个或更少的部分来作弊。

const getDomainWithoutSubdomain = url => {
  const urlParts = new URL(url).hostname.split('.')

  return urlParts
    .slice(0)
    .slice(-(urlParts.length === 4 ? 3 : 2))
    .join('.')
}

[
  'https://www.google.com',
  'https://www.google.co.uk',
  'https://mail.google.com',
  'https://www.bbc.co.uk/news',
  'https://github.com',
].forEach(url => {
  console.log(getDomainWithoutSubdomain(url))
})

domain.com.hk 返回 com.hk
2021-05-01 16:52:15

你可以用来parse-domain为你做繁重的工作。这个包考虑public suffix list并返回一个易于处理的对象分解域。

这是他们自述文件中的一个示例:

  npm install parse-domain
  import { parseDomain, ParseResultType } from 'parse-domain';

  const parseResult = parseDomain(
    // should be a string with basic latin characters only. more details in the readme
    'www.some.example.co.uk',
  );

  // check if the domain is listed in the public suffix list
  if (parseResult.type === ParseResultType.Listed) {
    const { subDomains, domain, topLevelDomains } = parseResult;

    console.log(subDomains); // ["www", "some"]
    console.log(domain); // "example"
    console.log(topLevelDomains); // ["co", "uk"]
  } else {
    // more about other parseResult types in the readme
  }

这对我有用:

const firstTLDs = "ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jo|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|na|nc|ne|nf|ng|nl|no|nr|nu|nz|om|pa|pe|pf|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt".split('|');

const secondTLDs = "com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc".split('|');

const knownSubdomains = "www|studio|mail|remote|blog|webmail|server|ns1|ns2|smtp|secure|vpn|m|shop|ftp|mail2|test|portal|ns|ww1|host|support|dev|web|bbs|ww42|squatter|mx|email|1|mail1|2|forum|owa|www2|gw|admin|store|mx1|cdn|api|exchange|app|gov|2tty|vps|govyty|hgfgdf|news|1rer|lkjkui";

function removeSubdomain(s) {
    const knownSubdomainsRegExp = new RegExp(`^(${knownSubdomains})\.`, 'i');
    s = s.replace(knownSubdomainsRegExp, '');

    const parts = s.split('.');

    while (parts.length > 3) {
        parts.shift();
    }

    if (parts.length === 3 && ((parts[1].length > 2 && parts[2].length > 2) || (secondTLDs.indexOf(parts[1]) === -1) && firstTLDs.indexOf(parts[2]) === -1)) {
        parts.shift();
    }

    return parts.join('.');
};

var tests = {
  'www.sidanmor.com':             'sidanmor.com',
  'exemple.com':                  'exemple.com',
  'argos.co.uk':                  'argos.co.uk',
  'www.civilwar.museum':          'civilwar.museum',
  'www.sub.civilwar.museum':      'civilwar.museum',
  'www.xxx.sub.civilwar.museum':  'civilwar.museum',
  'www.exemple.com':              'exemple.com',
  'main.testsite.com':            'testsite.com',
  'www.ex-emple.com.ar':          'ex-emple.com.ar',
  'main.test-site.co.uk':         'test-site.co.uk',
  'en.tour.mysite.nl':            'tour.mysite.nl',
  'www.one.lv':                   'one.lv',
  'www.onfdsadfsafde.lv':         'onfdsadfsafde.lv',
  'aaa.onfdsadfsafde.aa':         'onfdsadfsafde.aa',
};

const firstTLDs = "ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|be|bf|bg|bh|bi|bj|bm|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|cl|cm|cn|co|cr|cu|cv|cw|cx|cz|de|dj|dk|dm|do|dz|ec|ee|eg|es|et|eu|fi|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jo|jp|kg|ki|km|kn|kp|kr|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|na|nc|ne|nf|ng|nl|no|nr|nu|nz|om|pa|pe|pf|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|yt".split('|');

const secondTLDs = "com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc".split('|');

const knownSubdomains = "www|studio|mail|remote|blog|webmail|server|ns1|ns2|smtp|secure|vpn|m|shop|ftp|mail2|test|portal|ns|ww1|host|support|dev|web|bbs|ww42|squatter|mx|email|1|mail1|2|forum|owa|www2|gw|admin|store|mx1|cdn|api|exchange|app|gov|2tty|vps|govyty|hgfgdf|news|1rer|lkjkui";

function removeSubdomain(s) {
const knownSubdomainsRegExp = new RegExp(`^(${knownSubdomains})\.`, 'i');
s = s.replace(knownSubdomainsRegExp, '');

const parts = s.split('.');

while (parts.length > 3) {
    parts.shift();
}

if (parts.length === 3 && ((parts[1].length > 2 && parts[2].length > 2) || (secondTLDs.indexOf(parts[1]) === -1) && firstTLDs.indexOf(parts[2]) === -1)) {
    parts.shift();
}

return parts.join('.');
};

for (var test in tests) {
  if (tests.hasOwnProperty(test)) {
    var t = test;
    var e = tests[test];
    var r = removeSubdomain(test);
    var s = e === r;
    if (s) {
      console.log('OK: "' + t + '" should be "' + e + '" and it is really "' + r + '"');
    } else {
      console.log('Fail: "' + t + '" should be "' + e + '" but it is NOT "' + r + '"');
    }
  }
}

参考资料:

psl.min.js 文件

马克西米利安·劳迈斯特 回答这个问题

互联网上最受欢迎的子域

我目前正在尝试找出一种方法来优化您的解决方案,因为它没有通过www.d7143.test.me. 它吐出d7143.test.me而不是test.me.
2021-04-24 16:52:15
是的,这是没用的,www.d7143.test.me 应该不加更改地返回 test.me
2021-04-27 16:52:15
您的列表不是最新的。截至今天,有 1584 个顶级域。iana.org/domains/root/db
2021-05-05 16:52:15
“我”在我的第一个顶级域名列表中。如果您想获得“test.me”,您可以将其从列表中删除...但我认为这样做不正确,因为有些网站将“me”作为 firstTLD...祝您好运!
2021-05-11 16:52:15
硬编码 TLD 不是一个好主意,因为新 TLD 的引入比您想象的要频繁得多,而且规则也可能会发生变化。
2021-05-11 16:52:15

最简单的解决方案:

var domain='https://'+window.location.hostname.split('.')[window.location.hostname.split('.').length-2]+'.'+window.location.hostname.split('.')[window.location.hostname.split('.').length-1];
alert(domain);