PHP的parse_url()有一个主机字段,其中包含完整的主机。我正在寻找最可靠(且成本最低)的方式来返回域和TLD。
举个例子:
我只想找 google.com 或 google.co.uk 。我已经考虑了一个有效的TLD /后缀表,只允许这些和一个单词。你会以其他方式做到吗?有没有人知道这种事情的预先有效的REGEX?
答案 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));
}
肯定会有效吗?