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

Cyc*_*one 30 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
Run Code Online (Sandbox Code Playgroud)

基本上,我需要能够匹配任何普通的URL.我如何example.com 通过单个正则表达式提取(或.net,无论tld恰好是什么.我需要这个与任何TLD一起工作.)

Tyl*_*ter 42

那么你可以parse_url用来获得主持人:

$info = parse_url($url);
$host = $info['host'];
Run Code Online (Sandbox Code Playgroud)

然后,你可以做一些花哨的东西,只获得TLD和主机

$host_names = explode(".", $host);
$bottom_host_name = $host_names[count($host_names)-2] . "." . $host_names[count($host_names)-1];
Run Code Online (Sandbox Code Playgroud)

不是很优雅,但应该工作.


如果你想要一个解释,这里是:

首先,我们http://通过使用parse_url......的功能来解析方案(等)之间的所有内容......解析URL.:)

然后我们获取主机名,并根据周期落在哪里将其分成一个数组,因此test.world.hello.myname将成为:

array("test", "world", "hello", "myname");
Run Code Online (Sandbox Code Playgroud)

之后,我们获取数组中的元素数量(4).

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

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

然后我们将这两个部分组合成一个句点,你就有了你的基本主机名.

  • 那些像'co.uk`这样的两段顶级域名呢? (43认同)
  • 被否决,因为这不支持域 ccTLD。 (4认同)

poc*_*sar 13

我在https://gist.github.com/pocesar/5366899中的解决方案

测试在这里http://codepad.viper-7.com/GAh1tP

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

许多域名都包含测试.

不会在这里粘贴函数,因为StackOverflow中的代码有奇怪的缩进(可能有像github一样的受防护的代码块)

  • @Bashevis编码用于主机名,而不是URL,您可以使用`parse_url('http://foo.bar.example.com/foo/bar',PHP_URL_HOST)轻松提取; (2认同)

mgu*_*utt 10

如果不使用TLD列表进行比较,则无法获取域名,因为它们存在许多具有完全相同结构和长度的案例:

  1. www.db.de(子域名)与bbc.co.uk(域名)
  2. big.uk.com(SLD)与www.uk.com(TLD)

Mozilla的公共后缀列表应该是所有主流浏览器使用的最佳选项:https:
//publicsuffix.org/list/public_suffix_list.dat

随意使用我的功能:

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 '';
}
Run Code Online (Sandbox Code Playgroud)

特别之处:

  • 它接受带有或不带方案的URL,主机名或域等所有输入
  • 列表是逐行下载的,以避免高内存使用量
  • 它在缓存文件夹中为每个TLD创建一个新文件,因此get_domain()只需要检查file_exists()它是否存在,这样就不需要像TLDExtract那样在每个请求中包含一个庞大的数据库.
  • 该列表将每30天自动更新一次

测试:

$urls = array(
    'http://www.example.com',// example.com
    'http://subdomain.example.com',// example.com
    'http://www.example.uk.com',// example.uk.com
    'http://www.example.co.uk',// example.co.uk
    'http://www.example.com.ac',// example.com.ac
    'http://example.com.ac',// example.com.ac
    'http://www.example.accident-prevention.aero',// example.accident-prevention.aero
    'http://www.example.sub.ar',// sub.ar
    'http://www.congresodelalengua3.ar',// congresodelalengua3.ar
    'http://congresodelalengua3.ar',// congresodelalengua3.ar
    'http://www.example.pvt.k12.ma.us',// example.pvt.k12.ma.us
    'http://www.example.lib.wy.us',// example.lib.wy.us
    'com',// empty
    '.com',// empty
    'http://big.uk.com',// big.uk.com
    'uk.com',// empty
    'www.uk.com',// www.uk.com
    '.uk.com',// empty
    'stackoverflow.com',// stackoverflow.com
    '.foobarfoo',// empty
    '',// empty
    false,// empty
    ' ',// empty
    1,// empty
    'a',// empty    
);
Run Code Online (Sandbox Code Playgroud)

带解释的最新版本(德语):http:
//www.programmierer-forum.de/domainnamen-ermitteln-t244185.htm

  • 您的问题没有意义,因为问题是提取域名.你想从`localhost`中提取什么? (2认同)

小智 7

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];
}
Run Code Online (Sandbox Code Playgroud)


小智 5

$onlyHostName = implode('.', array_slice(explode('.', parse_url($link, PHP_URL_HOST)), -2));
Run Code Online (Sandbox Code Playgroud)

  • 尝试在代码旁边提供解释.海报应该了解他在做什么.否则他将使用相同的问题创建moer问题. (5认同)

小智 5

我认为处理这个问题的最好方法是:

$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]";
}
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于.co.uk这样的扩展程序. (3认同)
  • 在TLD之后,这不适用于任何事情 (2认同)

hap*_*set 5

我建议将TLDExtract库用于所有带有域名的操作。