Как получить базовое доменное имя из URL с помощью PHP?

Мне нужно получить доменное имя из URL-адреса. Следующие примеры должны возвращать google.com:

google.com
images.google.com
new.images.google.com
www.google.com

Аналогично, все URL-адреса должны возвращать 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? Это необходимо для работы на всех платформах и хостах.

Ответы

Ответ 1

Вы можете сделать это:

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

Ответ 2

домены верхнего уровня и домены второго уровня могут иметь длину 2 символа, но зарегистрированный субдомен должен иметь длину не менее 3 символов.

EDIT: из-за комментария pjv я узнал, что австралийские доменные имена являются исключением, поскольку они позволяют 5 TLD в качестве SLD (com, net, org, asn, id) example: somedomain.com.au. Я предполагаю, что com.au является государственным доменным именем, которое "разделяет". так что технически "com.au" все равно будет "базовым доменом", но это не полезно.

EDIT: существует 47 952 возможных трехбуквенных имени домена (шаблон: [a-zA-Z0-9] [a-zA-Z0-9 -] [a-zA-Z0-9] или 36 * 37 * 36) в сочетании с 8 наиболее распространенными TLDS (com, org и т.д.), У нас есть 383 616 возможностей - даже без добавления во весь диапазон TLD. Однобуквенные и двухбуквенные имена доменов все еще существуют, но недействительны в будущем.

в google.com - "google" является субдоменом "com" ​​

в google.co.uk - "google" является субдоменом "co", который, в свою очередь, является субдоменом "uk" или доменом второго уровня, так как "co" также является действительным верхом -областной домен

на www.google.com - "www" является субдоменом "google" , который является субдоменом "com" ​​

"co.uk" НЕ является допустимым хостом, потому что нет действительного имени домена

исходя из этого предположения, эта функция вернет правильный "basedomain" почти во всех случаях, не требуя "карты url".

если вы оказались одним из редких случаев, возможно, вы можете изменить это, чтобы удовлетворить особые потребности...

РЕДАКТИРОВАТЬ: вы должны передать доменную строку в качестве 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, чтобы открыть этот URL: http://data.iana.org/TLD/tlds-alpha-by-domain.txt

затем прочитайте строки в массиве и используйте это для сравнения частей домена

EDIT: разрешить австралийские домены:

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. Это удобно для внутреннего использования, но это далеко от полного процесса проверки домена. Если вы пытаетесь использовать его таким образом, я рекомендую не использовать слишком много возможностей для сопоставления недопустимых доменов.

Ответ 3

Попробуйте использовать: 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];

Ответ 4

Используйте эту функцию:

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

Ответьте на все варианты URL-адреса примера.