12

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

给定示例:

我只寻找google.comgoogle.co.uk。我已经考虑了一个有效的顶级域名/后缀表,并且只允许这些和一个单词。你会用其他方法吗?有谁知道这种事情的预装有效正则表达式?

4

8 回答 8

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。

// 附录:

阿尔尼塔克是对的。上面介绍的解决方案在大多数情况下都有效,但不一定适用于所有情况,并且需要进行维护以确保它们不是具有 .morethan6characters 等的新 TLD。提取域的唯一可靠方法是使用维护列表,例如http://publicsuffix.org/。一开始会更痛苦,但从长远来看会更容易、更健壮。您需要确保了解每种方法的优缺点以及它如何适合您的项目。

于 2008-12-30T01:51:39.963 回答
6

目前,唯一“正确”的方法是使用一个列表,例如在http://publicsuffix.org/上维护的列表

顺便说一句,这个问题也几乎是重复的:

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

于 2008-12-30T20:47:14.697 回答
4

Python 的 tldextract 模块还有一个非常好的端口http://w-shadow.com/blog/2012/08/28/tldextract - 这超出了 parse_url 并允许您在没有子域的情况下实际获取域/tld .

从模块网站:

$components = tldextract('http://www.bbc.co.uk');
echo $components->subdomain; // www
echo $components->domain;    // bbc
echo $components->tld;       // co.uk
于 2013-10-02T12:57:12.950 回答
1

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

我宁愿不那样做。

于 2008-12-30T01:03:35.943 回答
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'
于 2016-07-01T14:46:08.677 回答
0

当然,这取决于您的具体用例,但一般来说,我不会对 TLD 使用表查找。新的 TLD 出现了,您通常不想在任何地方维护它们。问问我的 firstname@lastname.name 多久因为短视而被拒绝。

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

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

于 2008-12-30T01:06:49.557 回答
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
    }
?>
于 2008-12-30T01:39:40.910 回答
-3

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

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

这肯定会奏效吗?

于 2009-01-01T01:29:12.347 回答