在php中获取域名(不是子域)

在php中获取域名(不是子域),php,regex,domain-name,Php,Regex,Domain Name,我有一个URL,可以是以下任意格式: http://example.com https://example.com http://example.com/foo http://example.com/foo/bar www.example.com example.com foo.example.com www.foo.example.com foo.bar.example.com http://foo.bar.example.com/foo/bar example.net/foo/bar 本质

我有一个URL,可以是以下任意格式:

http://example.com
https://example.com
http://example.com/foo
http://example.com/foo/bar
www.example.com
example.com
foo.example.com
www.foo.example.com
foo.bar.example.com
http://foo.bar.example.com/foo/bar
example.net/foo/bar

本质上,我需要能够匹配任何正常的URL。如何通过单个正则表达式从所有这些文件中提取
example.com
(或.net,无论tld是什么。我需要它来处理任何tld。)

您可以使用
解析url
获取主机:

$info = parse_url($url);
$host = $info['host'];
然后,您可以做一些奇特的事情,只获得TLD和主机

$host_names = explode(".", $host);
$bottom_host_name = $host_names[count($host_names)-2] . "." . $host_names[count($host_names)-1];
不是很优雅,但应该有用


如果您需要解释,请看下面的内容:

首先,我们通过使用
parse\u url
的功能来获取方案之间的所有内容(
http://
,等等)。。。好。。。。解析URL:)

然后我们获取主机名,并根据句点所在的位置将其分隔成一个数组,因此
test.world.hello.myname
将变成:

array("test", "world", "hello", "myname");
然后,我们取数组中的元素数(4)

然后,我们从中减去2,得到倒数第二个字符串(在您的示例中是主机名,或
example

然后,我们从中减去1得到最后一个字符串(因为数组键从0开始),也称为TLD


然后我们将这两部分用句号组合起来,您就有了基本主机名。

如果不使用TLD列表进行比较,就不可能获得域名,因为它们存在许多结构和长度完全相同的情况:

  • www.db.de(子域)与bbc.co.uk(域)
  • big.uk.com(SLD)与www.uk.com(TLD)
  • Mozilla的公共后缀列表应该是最好的选择,因为它被所有人使用:

    请随意使用我的功能:

    function tld_list($cache_dir=null) {
        // we use "/tmp" if $cache_dir is not set
        $cache_dir = isset($cache_dir) ? $cache_dir : sys_get_temp_dir();
        $lock_dir = $cache_dir . '/public_suffix_list_lock/';
        $list_dir = $cache_dir . '/public_suffix_list/';
        // refresh list all 30 days
        if (file_exists($list_dir) && @filemtime($list_dir) + 2592000 > time()) {
            return $list_dir;
        }
        // use exclusive lock to avoid race conditions
        if (!file_exists($lock_dir) && @mkdir($lock_dir)) {
            // read from source
            $list = @fopen('https://publicsuffix.org/list/public_suffix_list.dat', 'r');
            if ($list) {
                // the list is older than 30 days so delete everything first
                if (file_exists($list_dir)) {
                    foreach (glob($list_dir . '*') as $filename) {
                        unlink($filename);
                    }
                    rmdir($list_dir);
                }
                // now set list directory with new timestamp
                mkdir($list_dir);
                // read line-by-line to avoid high memory usage
                while ($line = fgets($list)) {
                    // skip comments and empty lines
                    if ($line[0] == '/' || !$line) {
                        continue;
                    }
                    // remove wildcard
                    if ($line[0] . $line[1] == '*.') {
                        $line = substr($line, 2);
                    }
                    // remove exclamation mark
                    if ($line[0] == '!') {
                        $line = substr($line, 1);
                    }
                    // reverse TLD and remove linebreak
                    $line = implode('.', array_reverse(explode('.', (trim($line)))));
                    // we split the TLD list to reduce memory usage
                    touch($list_dir . $line);
                }
                fclose($list);
            }
            @rmdir($lock_dir);
        }
        // repair locks (should never happen)
        if (file_exists($lock_dir) && mt_rand(0, 100) == 0 && @filemtime($lock_dir) + 86400 < time()) {
            @rmdir($lock_dir);
        }
        return $list_dir;
    }
    function get_domain($url=null) {
        // obtain location of public suffix list
        $tld_dir = tld_list();
        // no url = our own host
        $url = isset($url) ? $url : $_SERVER['SERVER_NAME'];
        // add missing scheme      ftp://            http:// ftps://   https://
        $url = !isset($url[5]) || ($url[3] != ':' && $url[4] != ':' && $url[5] != ':') ? 'http://' . $url : $url;
        // remove "/path/file.html", "/:80", etc.
        $url = parse_url($url, PHP_URL_HOST);
        // replace absolute domain name by relative (http://www.dns-sd.org/TrailingDotsInDomainNames.html)
        $url = trim($url, '.');
        // check if TLD exists
        $url = explode('.', $url);
        $parts = array_reverse($url);
        foreach ($parts as $key => $part) {
            $tld = implode('.', $parts);
            if (file_exists($tld_dir . $tld)) {
                return !$key ? '' : implode('.', array_slice($url, $key - 1));
            }
            // remove last part
            array_pop($parts);
        }
        return '';
    }
    
    最新版本及解释(德语):

    使用
    https://subdomain.domain.com/some/path
    作为示例

    parse\u url($link,PHP\u url\u HOST)
    返回
    subdomain.domain.com

    分解('.',解析url($link,PHP\u url\u HOST))
    然后将
    subdomain.domain.com
    分解成一个数组:

    array(3) {
      [0]=>
      string(5) "subdomain"
      [1]=>
      string(7) "domain"
      [2]=>
      string(3) "com"
    }
    
    array\u slice
    然后对数组进行切片,使数组中仅包含最后2个值(由
    -2
    表示):

    内爆
    然后将这两个数组值组合在一起,最终得到
    domain.com

    注意:只有当您期望的终端域中只有一个
    时,这才有效,例如
    something.domain.com
    else.something.domain.net

    它不适用于
    something.domain.co.uk
    ,您希望
    domain.co.uk

    我的解决方案

    测试就在这里

    它适用于任何TLD和可怕的子域模式(最多3个子域)

    有一个测试包含了许多域名


    由于StackOverflow中的代码有奇怪的缩进(可能有github这样的防护代码块),因此不会将函数粘贴到此处。

    我认为处理此问题的最佳方法是:

    $second_level_domains_regex = '/\.asn\.au$|\.com\.au$|\.net\.au$|\.id\.au$|\.org\.au$|\.edu\.au$|\.gov\.au$|\.csiro\.au$|\.act\.au$|\.nsw\.au$|\.nt\.au$|\.qld\.au$|\.sa\.au$|\.tas\.au$|\.vic\.au$|\.wa\.au$|\.co\.at$|\.or\.at$|\.priv\.at$|\.ac\.at$|\.avocat\.fr$|\.aeroport\.fr$|\.veterinaire\.fr$|\.co\.hu$|\.film\.hu$|\.lakas\.hu$|\.ingatlan\.hu$|\.sport\.hu$|\.hotel\.hu$|\.ac\.nz$|\.co\.nz$|\.geek\.nz$|\.gen\.nz$|\.kiwi\.nz$|\.maori\.nz$|\.net\.nz$|\.org\.nz$|\.school\.nz$|\.cri\.nz$|\.govt\.nz$|\.health\.nz$|\.iwi\.nz$|\.mil\.nz$|\.parliament\.nz$|\.ac\.za$|\.gov\.za$|\.law\.za$|\.mil\.za$|\.nom\.za$|\.school\.za$|\.net\.za$|\.co\.uk$|\.org\.uk$|\.me\.uk$|\.ltd\.uk$|\.plc\.uk$|\.net\.uk$|\.sch\.uk$|\.ac\.uk$|\.gov\.uk$|\.mod\.uk$|\.mil\.uk$|\.nhs\.uk$|\.police\.uk$/';
    $domain = $_SERVER['HTTP_HOST'];
    $domain = explode('.', $domain);
    $domain = array_reverse($domain);
    if (preg_match($second_level_domains_regex, $_SERVER['HTTP_HOST']) {
        $domain = "$domain[2].$domain[1].$domain[0]";
    } else {
        $domain = "$domain[1].$domain[0]";
    }
    

    这是我写的一个函数,用来抓取没有子域的域,不管域是使用ccTLD还是新样式的长TLD,等等。。。没有查找或大量已知TLD,也没有正则表达式。使用三元运算符和嵌套可以缩短很多,但为了可读性,我扩展了它

    // Per Wikipedia: "All ASCII ccTLD identifiers are two letters long, 
    // and all two-letter top-level domains are ccTLDs."
    
    function topDomainFromURL($url) {
      $url_parts = parse_url($url);
      $domain_parts = explode('.', $url_parts['host']);
      if (strlen(end($domain_parts)) == 2 ) { 
        // ccTLD here, get last three parts
        $top_domain_parts = array_slice($domain_parts, -3);
      } else {
        $top_domain_parts = array_slice($domain_parts, -2);
      }
      $top_domain = implode('.', $top_domain_parts);
      return $top_domain;
    }
    

    我建议对所有具有域名的操作使用库。

    我对pocesar提供的解决方案有问题。 当我使用subdomain.domain.nl作为实例时,它不会返回domain.nl。相反,它将返回subdomain.domain.nl 另一个问题是domain.com.br将返回com.br

    我不确定,但我用以下代码解决了这些问题(我希望它能帮助别人,如果是这样的话,我是一个快乐的人):

    函数get\u domain($domain,$debug=false){ $original=$domain=strtolower($domain); if(过滤器变量($domain,过滤器验证IP)){ 返回$domain; } $debug?打印('»;解析:'.$original):false; $arr=array\u切片(array\u过滤器(分解('.',$domain,4),函数($value){ 返回$value!=“www”; }),0);//重新生成数组索引 如果(计数($arr)>2){ $count=计数($arr); $_sub=explode('.',$count==4?$arr[3]:$arr[2]); $debug?print(((部件计数:{$count})”):false; 如果(计数($_sub)==2){//两级TLD $removed=阵列移位($arr); 如果($count==4){//得到一个子域作为域 $removed=阵列移位($arr); } $debug?print(“
    \n”[*]两级TLD:”。join(“,$”sub)。”):false; }elseif(计数($\u sub)==1){//一级TLD $removed=array_shift($arr);//删除子域 如果(strlen($arr[0])==2&&$count==3){//TLD域必须是2个字母 阵列移动($arr,$removed); }elseif(strlen($arr[0])==3&&$count==3){ 阵列移动($arr,$removed); }否则{ //根据IANA的非国家TLD $tlds=阵列( "航空",, “arpa”, "亚洲",, “生意”, “猫”, "com",, “合作社”, "edu",, "政府",, “信息”, “工作”, “mil”, "摩比",, “博物馆”, “姓名”, “净”, "组织",, "岗位",, "亲",, ‘电话’, “旅行”, “xxx”, ); 如果(count($arr)>2&&in_数组($\u sub[0],$TLD)!==false){//特殊TLD没有国家/地区 阵列移位($arr); } } $debug?打印(“
    \n”。”[*]
    array(2) {
      [0]=>
      string(6) "domain"
      [1]=>
      string(3) "com"
    }
    
    $second_level_domains_regex = '/\.asn\.au$|\.com\.au$|\.net\.au$|\.id\.au$|\.org\.au$|\.edu\.au$|\.gov\.au$|\.csiro\.au$|\.act\.au$|\.nsw\.au$|\.nt\.au$|\.qld\.au$|\.sa\.au$|\.tas\.au$|\.vic\.au$|\.wa\.au$|\.co\.at$|\.or\.at$|\.priv\.at$|\.ac\.at$|\.avocat\.fr$|\.aeroport\.fr$|\.veterinaire\.fr$|\.co\.hu$|\.film\.hu$|\.lakas\.hu$|\.ingatlan\.hu$|\.sport\.hu$|\.hotel\.hu$|\.ac\.nz$|\.co\.nz$|\.geek\.nz$|\.gen\.nz$|\.kiwi\.nz$|\.maori\.nz$|\.net\.nz$|\.org\.nz$|\.school\.nz$|\.cri\.nz$|\.govt\.nz$|\.health\.nz$|\.iwi\.nz$|\.mil\.nz$|\.parliament\.nz$|\.ac\.za$|\.gov\.za$|\.law\.za$|\.mil\.za$|\.nom\.za$|\.school\.za$|\.net\.za$|\.co\.uk$|\.org\.uk$|\.me\.uk$|\.ltd\.uk$|\.plc\.uk$|\.net\.uk$|\.sch\.uk$|\.ac\.uk$|\.gov\.uk$|\.mod\.uk$|\.mil\.uk$|\.nhs\.uk$|\.police\.uk$/';
    $domain = $_SERVER['HTTP_HOST'];
    $domain = explode('.', $domain);
    $domain = array_reverse($domain);
    if (preg_match($second_level_domains_regex, $_SERVER['HTTP_HOST']) {
        $domain = "$domain[2].$domain[1].$domain[0]";
    } else {
        $domain = "$domain[1].$domain[0]";
    }
    
    // Per Wikipedia: "All ASCII ccTLD identifiers are two letters long, 
    // and all two-letter top-level domains are ccTLDs."
    
    function topDomainFromURL($url) {
      $url_parts = parse_url($url);
      $domain_parts = explode('.', $url_parts['host']);
      if (strlen(end($domain_parts)) == 2 ) { 
        // ccTLD here, get last three parts
        $top_domain_parts = array_slice($domain_parts, -3);
      } else {
        $top_domain_parts = array_slice($domain_parts, -2);
      }
      $top_domain = implode('.', $top_domain_parts);
      return $top_domain;
    }
    
    function get_domain($domain, $debug = false){
        $original = $domain = strtolower($domain);
        if (filter_var($domain, FILTER_VALIDATE_IP)) {
            return $domain;
        }
        $debug ? print('<strong style="color:green">&raquo;</strong> Parsing: '.$original) : false;
        $arr = array_slice(array_filter(explode('.', $domain, 4), function($value){
            return $value !== 'www';
        }), 0); //rebuild array indexes
        if (count($arr) > 2){
            $count = count($arr);
            $_sub = explode('.', $count === 4 ? $arr[3] : $arr[2]);
            $debug ? print(" (parts count: {$count})") : false;
            if (count($_sub) === 2){ // two level TLD
                $removed = array_shift($arr);
                if ($count === 4){ // got a subdomain acting as a domain
                    $removed = array_shift($arr);
                }
                $debug ? print("<br>\n" . '[*] Two level TLD: <strong>' . join('.', $_sub) . '</strong> ') : false;
            }elseif (count($_sub) === 1){ // one level TLD
                $removed = array_shift($arr); //remove the subdomain
                if (strlen($arr[0]) === 2 && $count === 3){ // TLD domain must be 2 letters
                    array_unshift($arr, $removed);
                }elseif(strlen($arr[0]) === 3 && $count === 3){
                    array_unshift($arr, $removed);
                }else{
                    // non country TLD according to IANA
                    $tlds = array(
                        'aero',
                        'arpa',
                        'asia',
                        'biz',
                        'cat',
                        'com',
                        'coop',
                        'edu',
                        'gov',
                        'info',
                        'jobs',
                        'mil',
                        'mobi',
                        'museum',
                        'name',
                        'net',
                        'org',
                        'post',
                        'pro',
                        'tel',
                        'travel',
                        'xxx',
                    );
                    if (count($arr) > 2 && in_array($_sub[0], $tlds) !== false){ //special TLD don't have a country
                        array_shift($arr);
                    }
                }
                $debug ? print("<br>\n" .'[*] One level TLD: <strong>'.join('.', $_sub).'</strong> ') : false;
            }else{ // more than 3 levels, something is wrong
                for ($i = count($_sub); $i > 1; $i--){
                    $removed = array_shift($arr);
                }
                $debug ? print("<br>\n" . '[*] Three level TLD: <strong>' . join('.', $_sub) . '</strong> ') : false;
            }
        }elseif (count($arr) === 2){
            $arr0 = array_shift($arr);
            if (strpos(join('.', $arr), '.') === false && in_array($arr[0], array('localhost','test','invalid')) === false){ // not a reserved domain
                $debug ? print("<br>\n" .'Seems invalid domain: <strong>'.join('.', $arr).'</strong> re-adding: <strong>'.$arr0.'</strong> ') : false;
                // seems invalid domain, restore it
                array_unshift($arr, $arr0);
            }
        }
        $debug ? print("<br>\n".'<strong style="color:gray">&laquo;</strong> Done parsing: <span style="color:red">' . $original . '</span> as <span style="color:blue">'. join('.', $arr) ."</span><br>\n") : false;
        return join('.', $arr);
    }
    
    function get_domaininfo($url) {
        // regex can be replaced with parse_url
        preg_match("/^(https|http|ftp):\/\/(.*?)\//", "$url/" , $matches);
        $parts = explode(".", $matches[2]);
        $tld = array_pop($parts);
        $host = array_pop($parts);
        if ( strlen($tld) == 2 && strlen($host) <= 3 ) {
            $tld = "$host.$tld";
            $host = array_pop($parts);
        }
    
        return array(
            'protocol' => $matches[1],
            'subdomain' => implode(".", $parts),
            'domain' => "$host.$tld",
            'host'=>$host,'tld'=>$tld
        );
    }
    
    print_r(get_domaininfo('http://mysubdomain.domain.co.uk/index.php'));
    
    Array
    (
        [protocol] => https
        [subdomain] => mysubdomain
        [domain] => domain.co.uk
        [host] => domain
        [tld] => co.uk
    )
    
    function strip_subdomains($url){
    
        # credits to gavingmiller for maintaining this list
        $second_level_domains = file_get_contents("https://raw.githubusercontent.com/gavingmiller/second-level-domains/master/SLDs.csv");
    
        # presume sld first ...
        $possible_sld = implode('.', array_slice(explode('.', $url), -2));
    
        # and then verify it
        if (strpos($second_level_domains, $possible_sld)){
            return  implode('.', array_slice(explode('.', $url), -3));
        } else {
            return  implode('.', array_slice(explode('.', $url), -2));
        }
    }
    
    <?php
      $host = $_SERVER['HTTP_HOST'];
      preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
      echo "domain name is: {$matches[0]}\n";
    ?>
    
       preg_match('/(www.)?([^.]+\.[^.]+)$/', $yourHost, $matches);
    
       echo "domain name is: {$matches[0]}\n"; 
    
    echo getDomainOnly("http://example.com/foo/bar");
    
    function getDomainOnly($host){
        $host = strtolower(trim($host));
        $host = ltrim(str_replace("http://","",str_replace("https://","",$host)),"www.");
        $count = substr_count($host, '.');
        if($count === 2){
            if(strlen(explode('.', $host)[1]) > 3) $host = explode('.', $host, 2)[1];
        } else if($count > 2){
            $host = getDomainOnly(explode('.', $host, 2)[1]);
        }
        $host = explode('/',$host);
        return $host[0];
    }
    
    function get_domain_regex($url){
      $pieces = parse_url($url);
      $domain = isset($pieces['host']) ? $pieces['host'] : '';
      if (preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)) {
        return $regs['domain'];
      }else{
        return false;
      }
    }
    
    function get_domain($url){
      $parseUrl = parse_url($url);
      $host = $parseUrl['host'];
      $host_array = explode(".", $host);
      $domain = $host_array[count($host_array)-2] . "." . $host_array[count($host_array)-1];
      return $domain;
    }
    
    (?:\.co)?(?:\.com)?(?:\.gov)?(?:\.net)?(?:\.org)?(?:\.id)?
    
        function get_domain_name($url){
          $pieces = parse_url($url);
          $domain = isset($pieces['host']) ? $pieces['host'] : $url;
          $domain = strtolower($domain);
          $domain = preg_replace('/.international$/', '.com', $domain);
          if (preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,90}\.[a-z\.]{2,6})$/i', $domain, $regs)) {
              if (preg_match('/(.*?)((?:\.co)?(?:\.com)?(?:\.gov)?(?:\.net)?(?:\.org)?(?:\.id)?(?:\.asn)?.[a-z]{2,6})$/i', $regs['domain'], $matches)) {
                  return $matches[1];
              }else  return $regs['domain'];
          }else{
            return $url;
          }
        }
    
    $url          = https://use.fontawesome.com/releases/v5.11.2/css/all.css?ver=2.7.5
    $handle       = pathinfo( parse_url( $url )['host'] )['filename'];
    $final_handle = substr( $handle , strpos( $handle , '.' ) + 1 );
    
    print_r($final_handle); // fontawesome 
    
    @preg_replace('#\/(.)*#', '', @preg_replace('#^https?://(www.)?#', '', $url))
    
    function getDomain($url){
        $pieces = parse_url($url);
        $domain = isset($pieces['host']) ? $pieces['host'] : '';
        if(preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)){
            return $regs['domain'];
        }
        return FALSE;
    }
    
    echo getDomain("http://example.com"); // outputs 'example.com'
    echo getDomain("http://www.example.com"); // outputs 'example.com'
    echo getDomain("http://mail.example.co.uk"); // outputs 'example.co.uk'