从 URL 中获取子域名

113

从URL中获取子域名一开始听起来很容易。

http://www.domain.example

查找第一个句点,然后返回“http://”之后的任何内容...

然后你记住了

http://super.duper.domain.example

哦,那么你认为,好的,找到最后一个句号,往回走一个单词并获取前面的所有内容!

然后你记得了

http://super.duper.domain.co.uk

你回到了起点。除了存储所有顶级域名的列表之外,还有没有其他好的想法?


1
这个问题在这里已经被问过了: 获取URL的部分 编辑:在这里也有一个类似的问题被问过 :) - jb.
1
你能澄清一下你想要什么吗?看起来你想要 URL 的“官方”域部分(即 domain.co.uk),无论在它之前有多少个 DNS 标签? - Alnitak
1
我认为这不是同一个问题 - 这似乎更多地涉及域名中的管理削减,仅通过查看字符串无法解决。 - Alnitak
1
我同意。请详细说明您的最终目标是什么。 - BuddyJoe
1
请查看此答案:https://dev59.com/WnE85IYBdhLWcg3wpFKu#39307593 - Ehsan Chavoshi
显示剩余2条评论
18个回答

0

这段代码返回正确的域名。

InternetDomainName foo = InternetDomainName.from("foo.item.shopatdoor.co.uk").topPrivateDomain(); System.out.println(foo.topPrivateDomain());


0

它并不能完全解决问题,但你可以尝试逐个获取域名的部分并检查响应,例如获取 'http://uk',然后是 'http://co.uk',最后是 'http://domain.co.uk'。当你获得非错误响应时,你就得到了域名,其余部分则是子域名。

有时候你只需要试一试 :)

编辑:

Tom Leys在评论中指出,有些域名仅在www子域名上设置,这将导致我们在上述测试中得到不正确的答案。好点子!也许最好的方法是使用 'http://www' 和 'http://' 检查每个部分,并将任何一个命中视为该域名部分的命中?我们仍然会错过一些“替代”安排,例如 'web.domain.com',但我已经很久没有遇到这种情况了 :)


好主意!进行一次whois查询可以澄清这个问题,尽管维护一个哪些whois服务器用于哪些顶级域名/二级域名的列表意味着需要解决边缘情况下的同样问题。 - jTresidder
你假设每个域名都运行着一个HTTP服务器。 - Francois Bourgeois
无法适用于.DK和其他一些情况,因为http://dk/可以直接使用。这种启发式方法并不可取... - Patrick Mevzek

0
echo tld('http://www.example.co.uk/test?123'); // co.uk

/**
 * http://publicsuffix.org/
 * http://www.alandix.com/blog/code/public-suffix/
 * http://tobyinkster.co.uk/blog/2007/07/19/php-domain-class/
 */
function tld($url_or_domain = null)
{
    $domain = $url_or_domain ?: $_SERVER['HTTP_HOST'];
    preg_match('/^[a-z]+:\/\//i', $domain) and 
        $domain = parse_url($domain, PHP_URL_HOST);
    $domain = mb_strtolower($domain, 'UTF-8');
    if (strpos($domain, '.') === false) return null;

    $url = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';

    if (($rules = file($url)) !== false)
    {
        $rules = array_filter(array_map('trim', $rules));
        array_walk($rules, function($v, $k) use(&$rules) { 
            if (strpos($v, '//') !== false) unset($rules[$k]);
        });

        $segments = '';
        foreach (array_reverse(explode('.', $domain)) as $s)
        {
            $wildcard = rtrim('*.'.$segments, '.');
            $segments = rtrim($s.'.'.$segments, '.');

            if (in_array('!'.$segments, $rules))
            {
                $tld = substr($wildcard, 2);
                break;
            }
            elseif (in_array($wildcard, $rules) or 
                    in_array($segments, $rules))
            {
                $tld = $segments;
            }
        }

        if (isset($tld)) return $tld;
    }

    return false;
}

0
private String getSubDomain(Uri url) throws Exception{
                        String subDomain =url.getHost();
                        String fial=subDomain.replace(".","/");
                        String[] arr_subDomain =fial.split("/");
                        return arr_subDomain[0];
                    }

第一个索引总是子域名


0
为了实现这一点,我编写了一个 Bash 函数,它依赖于 publicsuffix.org 数据和一个简单的正则表达式。
在 Ubuntu 18 上安装 publicsuffix.org 客户端:
sudo apt install psl

获取域名后缀(最长的后缀):

domain=example.com.tr
output=$(psl --print-unreg-domain $domain)

output 是:

example.com.tr: com.tr

其余的部分很简单,是基于bash的。从domain中提取后缀(com.tr),并测试它是否仍然有超过一个点。
# split output by colon
arr=(${output//:/ })
# remove the suffix from the domain
name=${1/${arr[1]}/}
# test
if [[ $name =~ \..*\. ]]; then
  echo "Yes, it is subdomain."
fi

将所有内容放在一个Bash函数中:

is_subdomain() {
  local output=$(psl --print-unreg-domain $1)
  local arr=(${output//:/ })
  local name=${1/${arr[1]}/}
  [[ $name =~ \..*\. ]]
}

使用方法:

d=example.com.tr
if is_subdomain $d; then
  echo "Yes, it is."
fi

0

您可以使用此库tld.js: JavaScript API来处理复杂的域名、子域名和URI。

tldjs.getDomain('mail.google.co.uk');
// -> 'google.co.uk'

如果您想在浏览器中获取根域名,可以使用这个库 AngusFu/browser-root-domain

var KEY = '__rT_dM__' + (+new Date());
var R = new RegExp('(^|;)\\s*' + KEY + '=1');
var Y1970 = (new Date(0)).toUTCString();

module.exports = function getRootDomain() {
  var domain = document.domain || location.hostname;
  var list = domain.split('.');
  var len = list.length;
  var temp = '';
  var temp2 = '';

  while (len--) {
    temp = list.slice(len).join('.');
    temp2 = KEY + '=1;domain=.' + temp;

    // try to set cookie
    document.cookie = temp2;

    if (R.test(document.cookie)) {
      // clear
      document.cookie = temp2 + ';expires=' + Y1970;
      return temp;
    }
  }
};

使用Cookie有些棘手。


-1

常见后缀列表(.co.uk,.com等)需要去除以及http://,这样你就只剩下“sub.domain”可以使用了,而不是“http://sub.domain.suffix”,至少我会这么做。

最大的问题在于可能的后缀列表。毕竟有很多种类


-3

快速查看publicsuffix.org清单后,我发现您可以通过移除域名的最后三个片段(“片段”在此处指两个点之间的一部分)来合理地近似,如果最后一个片段为两个字符长,则假设它是国家代码并将被进一步细分。如果最后一个片段是“us”,而倒数第二个片段也是两个字符,则移除最后四个片段。在所有其他情况下,删除最后两个片段。例如:

"

"example"不是两个字符,因此删除"domain.example",只留下"www"

" "

"example"不是两个字符,因此删除"domain.example",只留下"super.duper"

" "

"uk"是两个字符(但不是"us"),因此删除"domain.co.uk",只留下"super.duper"

" "

"us"是两个字符,表示"我们",再加上"wy"也是两个字符,所以删除"pvt.k12.wy.us",只留下"foo"。

请注意,虽然这对我迄今为止在回复中看到的所有示例都有效,但它仅仅是一个合理的近似值。它并不完全正确,尽管我认为这是你在没有制作/获取实际列表用于参考的情况下可能得到的最接近的结果。

"

3
有许多失败的案例。这是浏览器过去尝试使用的算法类型。不要这样做,使用PSL-它有效,并有助于您的库。 - Gervase Markham
没有任何限制gTLDs也可以被“划分”,例如,在.NAME开始时就是这种情况,那时你只能购买firstname.lastname.name域名。而在相反的方向上,现在.US也是平的,因此您可以通过仅购买注册表中的whatever.us来拥有x.y.z.whatever.us,然后您的算法将在其上失败。 - Patrick Mevzek
1
关于“段落”:在DNS世界中,这被称为标签,无需发明新名称。 - Patrick Mevzek

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