Розбір домену з URL-адреси


144

Мені потрібно побудувати функцію, яка аналізує домен з URL-адреси.

Отже, с

http://google.com/dhasjkdas/sadsdds/sdda/sdads.html

або

http://www.google.com/dhasjkdas/sadsdds/sdda/sdads.html

вона повинна повернутися google.com

з

http://google.co.uk/dhasjkdas/sadsdds/sdda/sdads.html

вона повинна повернутися google.co.uk.



9
@LightnessRacesinOrbit Це трохи більше, ніж просто "дивлячись у посібнику". PHP parse_url()повертає хост , а не домен .
MrWhite

1
@ w3dk: Це все ще було б фантастичною відправною точкою, що дозволило б цьому питанню parse_urlскоріше говорити про обмеження, а не про неясне "що я можу зробити".
Гонки легкості на орбіті

5
@LightnessRacesinOrbit ваш захист сумлінний, враховуючи вашу репутацію - простіше ви можете визнати, що ви не прочитали питання повністю
Енді Джонс

4
@LightnessRacesinOrbit Не обов'язково. support.suso.com/supki/…
Осінній Леонард

Відповіді:


297

Перевірте parse_url():

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$parse = parse_url($url);
echo $parse['host']; // prints 'google.com'

parse_url не дуже добре поводиться з погано розробленими URL-адресами, але добре, якщо ви, як правило, очікуєте гідних URL-адрес.


35
Одне, що parse_url () не робить - це лише повернути домен. Якщо ви додасте www.google.com або www.google.co.uk, він також поверне хост. Будь-які пропозиції щодо цього?
Гавін М. Рой



1
parse_url()можливо, проаналізуйте URL-адреси з доменом, який неправильно містить тире. Не вдалося знайти певного доказу, але перевірте цю помилку . FILTER_VALIDATE_URLвикористовує parse_url()внутрішньо.
XedinUnknown

8
Або просто: print parse_url($url, PHP_URL_HOST))якщо вам не потрібен $parseмасив ні для чого іншого.
rybo111

98
$domain = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));

Це повернутися б google.comдля обох http://google.com/ ... і http://www.google.com/ ...


18
тому що він все одно поверне сервер, якщо ви помістите "server.google.com" або "www3.google.com" ...
Патрік

Не всі субдомени є www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com - кілька прикладів.
rafark

23

Від http://us3.php.net/manual/en/function.parse-url.php#93983

з якоїсь дивної причини parse_url повертає хост (наприклад, example.com) як шлях, коли у вхідному URL-адресі не передбачена схема. Тому я написав швидку функцію, щоб отримати справжнього хоста:

function getHost($Address) { 
   $parseUrl = parse_url(trim($Address)); 
   return trim($parseUrl['host'] ? $parseUrl['host'] : array_shift(explode('/', $parseUrl['path'], 2))); 
} 

getHost("example.com"); // Gives example.com 
getHost("http://example.com"); // Gives example.com 
getHost("www.example.com"); // Gives www.example.com 
getHost("http://example.com/xyz"); // Gives example.com 

Не забудьте процитувати ваші рядки, як hostі path.
Gumbo

1
Якщо я використовую example.com, php відображає повідомлення: Message: Undefined index: hostякі ідеї це виправити?
Zim3r

1
На жаль, піддомен все ще включений у цей підхід, див. Приклад №3.
jenlampton

1
@ Zim3r Змініть першу частину терміналу на !empty($parseUrl['host']).
Demonslay335

LOL, якщо у нього немає схеми, це не URL-адреса.
miken32

12

Код, який мав на меті працювати на 100%, не здався для мене скороченням, я трохи зафіксував приклад, але знайшов код, який не допомагав і не мав проблем із цим. тому я змінив його на пару функцій (щоб увесь час запитувати список від Mozilla та видаляти кеш-систему). Це було протестовано на наборі 1000 URL-адрес і, здається, працює.

function domain($url)
{
    global $subtlds;
    $slds = "";
    $url = strtolower($url);

    $host = parse_url('http://'.$url,PHP_URL_HOST);

    preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
    foreach($subtlds as $sub){
        if (preg_match('/\.'.preg_quote($sub).'$/', $host, $xyz)){
            preg_match("/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/", $host, $matches);
        }
    }

    return @$matches[0];
}

function get_tlds() {
    $address = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';
    $content = file($address);
    foreach ($content as $num => $line) {
        $line = trim($line);
        if($line == '') continue;
        if(@substr($line[0], 0, 2) == '/') continue;
        $line = @preg_replace("/[^a-zA-Z0-9\.]/", '', $line);
        if($line == '') continue;  //$line = '.'.$line;
        if(@$line[0] == '.') $line = substr($line, 1);
        if(!strstr($line, '.')) continue;
        $subtlds[] = $line;
        //echo "{$num}: '{$line}'"; echo "<br>";
    }

    $subtlds = array_merge(array(
            'co.uk', 'me.uk', 'net.uk', 'org.uk', 'sch.uk', 'ac.uk', 
            'gov.uk', 'nhs.uk', 'police.uk', 'mod.uk', 'asn.au', 'com.au',
            'net.au', 'id.au', 'org.au', 'edu.au', 'gov.au', 'csiro.au'
        ), $subtlds);

    $subtlds = array_unique($subtlds);

    return $subtlds;    
}

Потім використовуйте його як

$subtlds = get_tlds();
echo domain('www.example.com') //outputs: example.com
echo domain('www.example.uk.com') //outputs: example.uk.com
echo domain('www.example.fr') //outputs: example.fr

Я знаю, що я мав би перетворити це на клас, але не встиг.


11
function get_domain($url = SITE_URL)
{
    preg_match("/[a-z0-9\-]{1,63}\.[a-z\.]{2,6}$/", parse_url($url, PHP_URL_HOST), $_domain_tld);
    return $_domain_tld[0];
}

get_domain('http://www.cdl.gr'); //cdl.gr
get_domain('http://cdl.gr'); //cdl.gr
get_domain('http://www2.cdl.gr'); //cdl.gr

Не працює для мене також: example.com // Неправильно: порожній рядок example.com // Правильно: example.com www.example.com // Неправильно: порожній рядок example.com/xyz // Правильно: example.com
jenlampton

Це чудова відповідь і заслуговує на більше кредиту. Просто додайте цей рядок як перший рядок у функції, і він також вирішує проблеми MangeshSathe та jenlampton: if ((substr ($ url, 0, strlen ('http: //')) <> 'http: //' ) && (substr ($ url, 0, strlen ('https: //')) <> 'https: //')) $ url = 'http: //'.$url;
Рік

4

Якщо ви хочете витягти хост із рядка http://google.com/dhasjkdas/sadsdds/sdda/sdads.html, використання parse_url () є прийнятним рішенням для вас.

Але якщо ви хочете витягнути домен або його частини, вам потрібен пакунок із використанням списку загального суфіксу . Так, ви можете використовувати рядкові функції arround parse_url (), але іноді це дасть неправильні результати.

Я рекомендую TLDExtract для розбору домену, ось зразок коду, який показує різницю:

$extract = new LayerShifter\TLDExtract\Extract();

# For 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html'

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';

parse_url($url, PHP_URL_HOST); // will return google.com

$result = $extract->parse($url);
$result->getFullHost(); // will return 'google.com'
$result->getRegistrableDomain(); // will return 'google.com'
$result->getSuffix(); // will return 'com'

# For 'http://search.google.com/dhasjkdas/sadsdds/sdda/sdads.html'

$url = 'http://search.google.com/dhasjkdas/sadsdds/sdda/sdads.html';

parse_url($url, PHP_URL_HOST); // will return 'search.google.com'

$result = $extract->parse($url);
$result->getFullHost(); // will return 'search.google.com'
$result->getRegistrableDomain(); // will return 'google.com'

Дуже дякую за цю пропозицію. Я ненавиджу додати ще одну бібліотеку за те, що здається простим завданням, але потім я побачив цю цитату в їхньому читанні, застосованому до мене: "Усі помиляються. Розщеплення на". " і прийняття останніх двох елементів проходить довгий шлях, лише якщо ви думаєте про прості домени .com. Наприклад, подумайте, наприклад, для аналізу форуму forums.bbc.co.uk : наївний метод розщеплення вище дасть вам "co" як домен і "uk" як TLD, а не "bbc" та "co.uk" відповідно. "
Demonslay335

Результат розбиття крапок, а не те, що ми хочемо статися в улюбленому домені .co.uk, насправді є правильним результатом, co є другим рівнем, а UK є найвищим рівнем. Вебмайстри часто цього не усвідомлюють.
Кріс

4

Я виявив, що рішення @ philfreo (на яке посилається php.net) досить добре отримує прекрасний результат, але в деяких випадках воно показує повідомлення "php" та "жорсткі стандарти" php. Тут виправлена ​​версія цього коду.

function getHost($url) { 
   $parseUrl = parse_url(trim($url)); 
   if(isset($parseUrl['host']))
   {
       $host = $parseUrl['host'];
   }
   else
   {
        $path = explode('/', $parseUrl['path']);
        $host = $path[0];
   }
   return trim($host); 
} 

echo getHost("http://example.com/anything.html");           // example.com
echo getHost("http://www.example.net/directory/post.php");  // www.example.net
echo getHost("https://example.co.uk");                      // example.co.uk
echo getHost("www.example.net");                            // example.net
echo getHost("subdomain.example.net/anything");             // subdomain.example.net
echo getHost("example.net");                                // example.net

2

Ось код, який я зробив, що на 100% знаходить лише доменне ім’я, оскільки він бере до уваги підписи mozilla sub tlds. Єдине, що вам потрібно перевірити, це те, як ви створюєте кеш цього файлу, тому ви не запитуєте mozilla кожен раз.

З якоїсь дивної причини доменів, таких як co.uk, немає в списку, тому вам доведеться здійснити деякий злом і додати їх вручну. Це не найчистіше рішення, але я сподіваюся, що він комусь допоможе.

//=====================================================
static function domain($url)
{
    $slds = "";
    $url = strtolower($url);

            $address = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';
    if(!$subtlds = @kohana::cache('subtlds', null, 60)) 
    {
        $content = file($address);
        foreach($content as $num => $line)
        {
            $line = trim($line);
            if($line == '') continue;
            if(@substr($line[0], 0, 2) == '/') continue;
            $line = @preg_replace("/[^a-zA-Z0-9\.]/", '', $line);
            if($line == '') continue;  //$line = '.'.$line;
            if(@$line[0] == '.') $line = substr($line, 1);
            if(!strstr($line, '.')) continue;
            $subtlds[] = $line;
            //echo "{$num}: '{$line}'"; echo "<br>";
        }
        $subtlds = array_merge(Array(
            'co.uk', 'me.uk', 'net.uk', 'org.uk', 'sch.uk', 'ac.uk', 
            'gov.uk', 'nhs.uk', 'police.uk', 'mod.uk', 'asn.au', 'com.au',
            'net.au', 'id.au', 'org.au', 'edu.au', 'gov.au', 'csiro.au',
            ),$subtlds);

        $subtlds = array_unique($subtlds);
        //echo var_dump($subtlds);
        @kohana::cache('subtlds', $subtlds);
    }


    preg_match('/^(http:[\/]{2,})?([^\/]+)/i', $url, $matches);
    //preg_match("/^(http:\/\/|https:\/\/|)[a-zA-Z-]([^\/]+)/i", $url, $matches);
    $host = @$matches[2];
    //echo var_dump($matches);

    preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
    foreach($subtlds as $sub) 
    {
        if (preg_match("/{$sub}$/", $host, $xyz))
        preg_match("/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/", $host, $matches);
    }

    return @$matches[0];
}

Причиною того, що домен co.ukне був у списку, було тому, що це список TLD, а не домени. CcTLD сильно змінився з часу написання цієї відповіді. Зокрема: "Нові реєстрації безпосередньо під .uk були прийняті Nominet з 10 червня 2014 року з 8:00 за тижнім часом, однак є період бронювання для існуючих клієнтів, які вже мають .co.uk, .org.uk, .me.uk , .net.uk, .ltd.uk або .plc.uk, щоб заявити відповідний домен .uk, який працює до 07:59 BST 10 червня 2019 року . " ( Джерело )
ashleedawg

2

Ви можете передати PHP_URL_HOST у функцію parse_url як другий параметр

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$host = parse_url($url, PHP_URL_HOST);
print $host; // prints 'google.com'

2
Це по суті те саме, що відповідь вище, однак, питання вимагає домену , який не обов'язково є таким самим, як хост .
MrWhite

дивіться коментар вище щодо схеми: з якоїсь дивної причини parse_url повертає хост (наприклад, example.com) як шлях, коли в URL-адресі введення не передбачено жодної схеми. Тому я написав швидку функцію, щоб отримати справжнього господаря:
jenlampton


2

Будь ласка, замініть прийняте рішення на таке:

parse_url () завжди буде включати будь-які субдомени, тому ця функція не дуже добре аналізує доменні імена. Ось кілька прикладів:

$url = 'http://www.google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$parse = parse_url($url);
echo $parse['host']; // prints 'www.google.com'

echo parse_url('https://subdomain.example.com/foo/bar', PHP_URL_HOST);
// Output: subdomain.example.com

echo parse_url('https://subdomain.example.co.uk/foo/bar', PHP_URL_HOST);
// Output: subdomain.example.co.uk

Натомість ви можете розглянути це прагматичне рішення. Він охоплюватиме багато, але не всі доменні імена - наприклад, домени нижчого рівня, такі як "sos.state.oh.us", не охоплюються.

function getDomain($url) {
    $host = parse_url($url, PHP_URL_HOST);

    if(filter_var($host,FILTER_VALIDATE_IP)) {
        // IP address returned as domain
        return $host; //* or replace with null if you don't want an IP back
    }

    $domain_array = explode(".", str_replace('www.', '', $host));
    $count = count($domain_array);
    if( $count>=3 && strlen($domain_array[$count-2])==2 ) {
        // SLD (example.co.uk)
        return implode('.', array_splice($domain_array, $count-3,3));
    } else if( $count>=2 ) {
        // TLD (example.com)
        return implode('.', array_splice($domain_array, $count-2,2));
    }
}

// Your domains
    echo getDomain('http://google.com/dhasjkdas/sadsdds/sdda/sdads.html'); // google.com
    echo getDomain('http://www.google.com/dhasjkdas/sadsdds/sdda/sdads.html'); // google.com
    echo getDomain('http://google.co.uk/dhasjkdas/sadsdds/sdda/sdads.html'); // google.co.uk

// TLD
    echo getDomain('https://shop.example.com'); // example.com
    echo getDomain('https://foo.bar.example.com'); // example.com
    echo getDomain('https://www.example.com'); // example.com
    echo getDomain('https://example.com'); // example.com

// SLD
    echo getDomain('https://more.news.bbc.co.uk'); // bbc.co.uk
    echo getDomain('https://www.bbc.co.uk'); // bbc.co.uk
    echo getDomain('https://bbc.co.uk'); // bbc.co.uk

// IP
    echo getDomain('https://1.2.3.45');  // 1.2.3.45

Нарешті, PHP Domain Parser Джеремі Кендалла дозволяє аналізувати доменне ім'я з URL-адреси. Розбір роботи URI також буде виконаний .


Привіт, це добре, але це не працює з IP-адресами. Все-таки чудова робота.
MeCe

1

parse_url не працював для мене. Це лише повернуло шлях. Перехід до основ за допомогою php5.3 +:

$url  = str_replace('http://', '', strtolower( $s->website));
if (strpos($url, '/'))  $url = strstr($url, '/', true);

1

Я змінив для вас:

function getHost($Address) { 
    $parseUrl = parse_url(trim($Address));
    $host = trim($parseUrl['host'] ? $parseUrl['host'] : array_shift(explode('/', $parseUrl['path'], 2))); 

    $parts = explode( '.', $host );
    $num_parts = count($parts);

    if ($parts[0] == "www") {
        for ($i=1; $i < $num_parts; $i++) { 
            $h .= $parts[$i] . '.';
        }
    }else {
        for ($i=0; $i < $num_parts; $i++) { 
            $h .= $parts[$i] . '.';
        }
    }
    return substr($h,0,-1);
}

Усі типи URL (www.domain.ltd, sub1.subn.domain.ltd призведе до: domain.ltd


1

Я додаю цю відповідь пізно, оскільки це відповідь, яка найбільше з'являється в Google ...

Ви можете використовувати PHP для ...

$url = "www.google.co.uk";
$host = parse_url($url, PHP_URL_HOST);
// $host == "www.google.co.uk"

захопити хост, але не приватний домен, на який хост посилається. (Приклад www.google.co.uk- хост, але google.co.ukце приватний домен)

Щоб схопити приватний домен, вам потрібно знати список загальнодоступних суфіксів, до яких можна зареєструвати приватний домен. Цей список може бути куратором Mozilla за адресою https://publicsuffix.org/

Код нижче працює, коли вже створено масив загальнодоступних суфіксів. Просто зателефонуйте

$domain = get_private_domain("www.google.co.uk");

з кодом, що залишився ...

// find some way to parse the above list of public suffix
// then add them to a PHP array
$suffix = [... all valid public suffix ...];

function get_public_suffix($host) {
  $parts = split("\.", $host);
  while (count($parts) > 0) {
    if (is_public_suffix(join(".", $parts)))
      return join(".", $parts);

    array_shift($parts);
  }

  return false;
}

function is_public_suffix($host) {
  global $suffix;
  return isset($suffix[$host]);
}

function get_private_domain($host) {
  $public = get_public_suffix($host);
  $public_parts = split("\.", $public);
  $all_parts = split("\.", $host);

  $private = [];

  for ($x = 0; $x < count($public_parts); ++$x) 
    $private[] = array_pop($all_parts);

  if (count($all_parts) > 0)
    $private[] = array_pop($all_parts);

  return join(".", array_reverse($private));
}

Згідно з моїм тестуванням, parse_url потребує добре сформованої URL-адреси. Якщо ви просто вкажете "www.someDomain.com/path", він повернеться до нуля. Тож очікується наявність протоколів (наприклад, http або https).
Енді

0

Як правило, це буде дуже добре, якщо вхідна URL-адреса не є загальним небажаним. Це видаляє субдомен.

$host = parse_url( $Row->url, PHP_URL_HOST );
$parts = explode( '.', $host );
$parts = array_reverse( $parts );
$domain = $parts[1].'.'.$parts[0];

Приклад

Вхід: http://www2.website.com:8080/some/file/structure?some=parameters

Вихід: website.com


0

Поєднання відповідей worldofjr та Alix Axel в одну невелику функцію, яка буде обробляти більшість випадків використання:

function get_url_hostname($url) {

    $parse = parse_url($url);
    return str_ireplace('www.', '', $parse['host']);

}

get_url_hostname('http://www.google.com/example/path/file.html'); // google.com

це обмежене рішення
MGE

0
function getTrimmedUrl($link)
{
    $str = str_replace(["www.","https://","http://"],[''],$link);
    $link = explode("/",$str);
    return strtolower($link[0]);                
}


-6

Просто використовуйте як наступне ...

<?php
   echo $_SERVER['SERVER_NAME'];
?>

1
Це якщо припустити, що сервер - це URL-адреса, з якої потрібно отримати домен. Це не так.
Overcode
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.