我需要从URL获取域名。以下示例都应返回google.com
:
google.com
images.google.com
new.images.google.com
www.google.com
同样,以下网址都应返回google.co.uk
。
google.co.uk
images.google.co.uk
new.images.google.co.uk
http://www.google.co.uk
我对使用正则表达式犹豫不决,因为domain.com/google.com
之类的内容可能会返回错误的结果。
如何使用PHP获取顶级域名?这需要适用于所有平台和主机。
答案 0 :(得分:17)
你可以这样做:
$urlData = parse_url($url);
$host = $urlData['host'];
**更新**
我能想到的最好的方法是绘制您想要处理的所有TLD的映射,因为某些TLD可能很棘手(co.uk)。
// you can add more to it if you want
$urlMap = array('com', 'co.uk');
$host = "";
$url = "http://www.google.co.uk";
$urlData = parse_url($url);
$hostData = explode('.', $urlData['host']);
$hostData = array_reverse($hostData);
if(array_search($hostData[1] . '.' . $hostData[0], $urlMap) !== FALSE) {
$host = $hostData[2] . '.' . $hostData[1] . '.' . $hostData[0];
} elseif(array_search($hostData[0], $urlMap) !== FALSE) {
$host = $hostData[1] . '.' . $hostData[0];
}
echo $host;
答案 1 :(得分:6)
顶级域名和二级域名的长度可能为2个字符,但注册的子域名长度必须至少为3个字符。
编辑:由于pjv的评论,我了解到澳大利亚域名是一个例外,因为它们允许5个TLD作为SLD(com,net,org,asn,id)示例:somedomain.com.au。我猜com.au是国家控制的域名“共享”。所以,从技术上讲,“com.au”仍然是“基础域”,但这没用。编辑:有47,952个可能的三字母域名(模式:[a-zA-Z0-9] [a-zA-Z0-9 - ] [a-zA-Z0-9]或36 * 37 * 36)与最常见的TLDS(com,org等)中的8个相结合,我们有383,616种可能性 - 甚至没有添加整个TLD范围。 1个字母和2个字母的域名仍然存在,但未来无效。
google.com中的- “google”是“com”
的子域名“co.uk”不是有效的主机,因为没有有效的域名
按照这个假设,这个函数几乎在所有情况下都会返回正确的“basedomain”,而不需要“url map”。
如果您碰巧是极少数情况之一,也许您可以修改它以满足特定需求......
编辑:您必须将域字符串作为带有协议的URL(http://,ftp://等)传递,否则parse_url()
将不会将其视为有效的URL(除非您要修改代码行为不同)
function basedomain( $str = '' )
{
// $str must be passed WITH protocol. ex: http://domain.com
$url = @parse_url( $str );
if ( empty( $url['host'] ) ) return;
$parts = explode( '.', $url['host'] );
$slice = ( strlen( reset( array_slice( $parts, -2, 1 ) ) ) == 2 ) && ( count( $parts ) > 2 ) ? 3 : 2;
return implode( '.', array_slice( $parts, ( 0 - $slice ), $slice ) );
}
如果您需要准确使用fopen
或curl
来打开此网址:
http://data.iana.org/TLD/tlds-alpha-by-domain.txt
然后将这些行读入数组并使用它来比较域部分
编辑:允许澳大利亚域名:
function au_basedomain( $str = '' )
{
// $str must be passed WITH protocol. ex: http://domain.com
$url = @parse_url( $str );
if ( empty( $url['host'] ) ) return;
$parts = explode( '.', $url['host'] );
$slice = ( strlen( reset( array_slice( $parts, -2, 1 ) ) ) == 2 ) && ( count( $parts ) > 2 ) ? 3 : 2;
if ( preg_match( '/\.(com|net|asn|org|id)\.au$/i', $url['host'] ) ) $slice = 3;
return implode( '.', array_slice( $parts, ( 0 - $slice ), $slice ) );
}
重要补充说明:我不使用此功能来验证域名。它是通用代码,我只用于从全局$_SERVER['SERVER_NAME']
中提取运行它的服务器的基本域,以便在各种内部脚本中使用。考虑到我只在美国境内工作,我从未遇到过pjv所询问的澳大利亚变种。它对内部使用很方便,但距离完整的域验证过程还有很长的路要走。如果您尝试以这种方式使用它,我建议不要因为有太多可能性来匹配无效域。
答案 2 :(得分:4)
尝试使用:http://php.net/manual/en/function.parse-url.php。这样的事情应该有效:
$urlParts = parse_url($yourUrl);
$hostParts = explode('.', $urlParts['host']);
$hostParts = array_reverse($hostParts);
$host = $hostParts[1] . '.' . $hostParts[0];
答案 3 :(得分:2)
与xil3混合回答这是我要检查localhost和ip,所以你也可以在开发环境中工作。
您仍需要定义要使用的TLD。除此之外一切正常。
<?php
function getTopLevelDomain($url){
$urlData = parse_url($url);
$urlHost = isset($urlData['host']) ? $urlData['host'] : '';
$isIP = (bool)ip2long($urlHost);
if($isIP){ /** To check if it's ip then return same ip */
return $urlHost;
}
/** Add/Edit you TLDs here */
$urlMap = array('com', 'com.pk', 'co.uk');
$host = "";
$hostData = explode('.', $urlHost);
if(isset($hostData[1])){ /** To check "localhost" because it'll be without any TLDs */
$hostData = array_reverse($hostData);
if(array_search($hostData[1] . '.' . $hostData[0], $urlMap) !== FALSE) {
$host = $hostData[2] . '.' . $hostData[1] . '.' . $hostData[0];
} elseif(array_search($hostData[0], $urlMap) !== FALSE) {
$host = $hostData[1] . '.' . $hostData[0];
}
return $host;
}
return ((isset($hostData[0]) && $hostData[0] != '') ? $hostData[0] : 'error no domain'); /* You can change this error in future */
}
?>
你可以像这样使用它
$string = 'http://googl.com.pk';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://googl.com.pk:23';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://googl.com';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://googl.com:23';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://adad.asdasd.googl.com.pk';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://adad.asdasd.googl.com.pk:23';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://adad.asdasd.googl.com';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://adad.asdasd.googl.com:23';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://192.168.0.101:23';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://192.168.0.101';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'http://localhost';
echo getTopLevelDomain( $string ) . '<br>';
$string = 'https;//';
echo getTopLevelDomain( $string ) . '<br>';
$string = '';
echo getTopLevelDomain( $string ) . '<br>';
你会得到像这样的字符串
的结果googl.com.pk
googl.com.pk
googl.com
googl.com
googl.com.pk
googl.com.pk
googl.com
googl.com
192.168.0.101
192.168.0.101
localhost
error no domain
error no domain
答案 4 :(得分:0)
我不是PHP开发人员,我知道这不是完整的解决方案,但是我认为一般的问题实际上是确定所有可能的公共域名。
幸运的是,在https://publicsuffix.org/list/维护着一个公共域列表。该列表分为两部分。第一部分是公共域名,其中包括这些注释中列出的许多域名,例如.com
和.com.au
。公共域名用===BEGIN ICANN DOMAINS===
和===END ICANN DOMAINS===
分隔。
如果仅加载ICANN DOMAINS列表,则可以标识顶级域名。但是需要PHP开发人员来解释如何有效地做到这一点:)
如果加载整个列表,那么您还可以获得有关私有子域的信息,例如github.io
下的私有子域。
答案 5 :(得分:0)
您可能要使用公共后缀列表。
在php ypu中可以使用regdom库来做到这一点:
答案 6 :(得分:-3)
使用此功能:
function getHost($url){
if (strpos($url,"http://")){
$httpurl=$url;
} else {
$httpurl="http://".$url;
}
$parse = parse_url($httpurl);
$domain=$parse['host'];
$portion=explode(".",$domain);
$count=sizeof($portion)-1;
if ($count>1){
$result=$portion[$count-1].".".$portion[$count];
} else {
$result=$domain;
}
return $result;
}
回答示例网址的所有变体。