去PHP parse_url()不去的地方';t-仅解析域

去PHP parse_url()不去的地方';t-仅解析域,php,dns,Php,Dns,PHP的parse_url()有一个主机字段,其中包括完整主机。我正在寻找只返回域和TLD的最可靠(也是成本最低)的方法 举例来说: ,parse_url()返回主机的www.google.com ,parse_url()返回主机的www.google.co.uk 我只找google.com或google.co.uk。我考虑了一个有效TLD/后缀表,只允许这些和一个单词。你会用其他方法吗?有人知道这类事情的预封装有效正则表达式吗?从相关帖子中找到了这一点,目的是保留一个表: 当然,这取决于您

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

举例来说:

  • ,parse_url()返回主机的www.google.com
  • ,parse_url()返回主机的www.google.co.uk

我只找google.comgoogle.co.uk。我考虑了一个有效TLD/后缀表,只允许这些和一个单词。你会用其他方法吗?有人知道这类事情的预封装有效正则表达式吗?

从相关帖子中找到了这一点,目的是保留一个表:


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

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


您还可以找到有关处理DNS记录的PHP函数的帮助,以了解有关DNS记录的更多信息,例如,请参见。

假设允许的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
    }
?>

像这样的怎么样

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;
}
它应该返回:

google.com
google.co.uk
google.com
google.co.uk
nothingelsethan.com
当然,如果无法通过,它将不会返回任何内容,因此请确保它是一个格式良好的URL

//附录:

阿尔尼塔克是对的。上述解决方案适用于大多数情况,但不一定适用于所有情况,并且需要进行维护,以确保它们不是新的TLD,具有超过6个字符等等。提取域的唯一可靠方法是使用维护的列表,例如。一开始会更痛苦,但从长远来看更容易、更强健。您需要确保了解每种方法的优缺点,以及它如何适合您的项目。

目前唯一“正确”的方法是使用一个列表,如

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


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

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

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

这肯定会奏效吗?

Python的tldextract模块还有一个非常好的端口-这超出了解析url的范围,允许您实际获取域/tld,而不需要子域

从模块网站:

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

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

我推荐使用。下面是代码示例:

$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'

我正在寻找使用它制作一个垃圾邮件发送者域名黑名单,并防止人们使用通配符DNS绕过它。与其说是电子邮件,不如说是博客或评论垃圾邮件。你已经提前做出了一个判断,我不确定这个判断是否正确,那就是你可以判断出主机的哪个部分是感兴趣的域名,它真的是TLD吗?例如,如果你只看标准域名,几乎任何dyndns域名都会被屏蔽。为了阻止来自www.mysite.isa-geek.org或mysite.isa-geek.org域的垃圾邮件,如果您阻止了所有isa-geek.org,您会介意吗?是的,在这种情况下,我可以阻止isa-geek.org。我最关心的是foo。[suffix],其中[suffix]是tld或标准后缀的组合。tld(co.uk)看这个:看这个答案:恐怕使用这个列表是唯一的方法。CCTLD的种类太多,无法编写解决方案来解决所有问题。该链接再次起作用,但只是重定向到该功能的所在地(“公共后缀列表”),有人否决该功能的原因吗?如果答案不对,或者有什么需要补充的,我们可以尝试改进。我否决了这个——这不是正确的答案。仅仅用一个简单的regexp无法确定“域部分”(即忽略“www”等)。请参阅其他链接的相关问题及其答案。publicsuffix.org列表是最可靠的方法。我不明白为什么这样做有效,但它确实有效。此外,它应该是
[a-z0-9][a-z0-9\-]{1,62}
,对吗?不适用于新的TLD或短域,如
$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'