去哪里PHP parse_url()没有 - 只解析域

时间:2008-12-30 00:51:48

标签: php dns

PHP的parse_url()有一个主机字段,其中包含完整的主机。我正在寻找最可靠(且成本最低)的方式来返回域和TLD。

举个例子:

我只想找 google.com google.co.uk 。我已经考虑了一个有效的TLD /后缀表,只允许这些和一个单词。你会以其他方式做到吗?有没有人知道这种事情的预先有效的REGEX?

8 个答案:

答案 0 :(得分:17)

这样的事情怎么样?

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;
}

将使用经典parse_url提取域名,然后查找没有任何子域的有效域(www是子域)。不会在'localhost'之类的东西上工作。如果不匹配,将返回false。

//编辑:

尝试使用:

echo getDomain('http://www.google.com/test.html') . '<br/>';
echo getDomain('https://news.google.co.uk/?id=12345') . '<br/>';
echo getDomain('http://my.subdomain.google.com/directory1/page.php?id=abc') . '<br/>';
echo getDomain('https://testing.multiple.subdomain.google.co.uk/') . '<br/>';
echo getDomain('http://nothingelsethan.com') . '<br/>';

它应该返回:

google.com
google.co.uk
google.com
google.co.uk
nothingelsethan.com

当然,如果它没有通过parse_url,它将不会返回任何内容,因此请确保它是一个格式正确的URL。

//附录:

Alnitak是对的。上面介绍的解决方案可以在大多数情况下工作,但不一定都需要维护,例如,确保它们不是具有.morethan6字符的新TLD等等。提取域的唯一可靠方法是使用维护列表,例如http://publicsuffix.org/。一开始它更痛苦但长期更容易和更强大。您需要确保了解每种方法的优缺点以及它如何适合您的项目。

答案 1 :(得分:6)

目前,执行此操作的唯一“正确”方法是使用维护在http://publicsuffix.org/

的列表 顺便说一下,这个问题也几乎与以下内容重复:

IETF正在进行标准化工作,寻找DNS方法来声明DNS树中的特定节点是否用于“公共”注册,但它们还处于早期开发阶段。所有流行的非IE浏览器都使用publicsuffix.org列表。

答案 2 :(得分:4)

Python的tldextract模块http://w-shadow.com/blog/2012/08/28/tldextract还有一个非常好的端口 - 这超出了parse_url,允许你实际获取domain / tld,而没有子域。

来自模块网站:

$components = tldextract('http://www.bbc.co.uk');
echo $components->subdomain; // www
echo $components->domain;    // bbc
echo $components->tld;       // co.uk

答案 3 :(得分:1)

从相关帖子中挖出这个,以保留表格的想法:http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/src/effective_tld_names.dat?raw=1

我宁愿不这样做。

答案 4 :(得分:1)

您需要使用Public Suffix List的软件包,只有这样您才能正确提取具有二级,三级TLD(co.uk,a.bg,b.bg等)和多级子域的域名。正则表达式,parse_url()或字符串函数永远不会产生绝对正确的结果。

我建议使用TLD Extract。这里是代码示例:

$extract = new LayerShifter\TLDExtract\Extract();

$result = $extract->parse('http://www.google.co.uk/foo');
$result->getSubdomain(); // will return (string) 'www'
$result->getHostname(); // will return (string) 'google'
$result->getSuffix(); // will return (string) 'co.uk'
$result->getRegistrableDomain(); // will return (string) 'google.co.uk'

答案 5 :(得分:0)

当然这取决于您的具体用例,但一般来说我不会对TLD使用表查找。新顶级域名出现了,您通常不希望将它们保留在任何地方。只要问我,我的firstname@lastname.name因为短视而被拒绝了。

如果我知道你为什么不想要www,我想我可以帮助更好?你需要它用于电子邮件吗?在这种情况下,您可以查询MX记录以验证它(最终)接受邮件。

您还可以找到有关处理DNS记录的PHP函数的帮助,以找到有关它们的更多信息,例如,请参阅http://php.net/dns_get_record

答案 6 :(得分:0)

只是一个证明,假设允许的tld被记忆成哈希。 代码可以缩短很多。

<?php
    $urlCompoments=parse_url($theUrl);
    $chunk=explode('.',$urlComponents['host']);

    $tldIndex = count($chunk-1); // assume last chunk is tld
    $maxTldLen = 2; // assuming a tld can be in the form .com or .co.uk
    $cursor=1;
    $found=false;
    while(($cursor<=$maxTldLen) or $found) {
      $tls = implode('.',array_slice($chunk, -$cursor));
      $found=isset($tldSuffixesAllowed[$tld]);
      $cursor++;
    }
    if ($found){
       $tld=implode('.',array_slice($chunk, -$cursor));
    } else {
       // domain not recognized, do wathever you want
    }
?>

答案 7 :(得分:-2)

有一个非常简单的解决方案:

function get_domain($url) {
  $pieces = parse_url($url);
  return array_pop(explode('.', $pieces['host'], 2));
}

肯定会有效吗?