Парсинг домена из URL

Мне нужно создать функцию, которая анализирует домен по 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.

см. этот: stackoverflow.com/questions/288810/get-the-subdomain-from-a-‌ url /…

Francois Bourgeois 04.02.2013 18:41

@LightnessRacesinOrbit Это немного больше, чем просто «заглядывать в руководство». parse_url() PHP возвращает хозяин, а не домен.

MrWhite 25.04.2016 17:45

@ w3dk: Это все равно было бы фантастической отправной точкой, если бы этот вопрос касался этого ограничения parse_url, а не расплывчатого «что я могу сделать».

Lightness Races in Orbit 25.04.2016 18:25

@LightnessRacesinOrbit ваша защита неискренняя, учитывая вашу репутацию - проще говоря, вы можете признать, что не прочитали вопрос полностью

Andy Jones 09.09.2016 02:22

@AndyJones: Я прекрасно прочитал вопрос, спасибо

Lightness Races in Orbit 09.09.2016 03:53

@LightnessRacesinOrbit Тогда каков ответ? Все еще ищу способ получить -domain-, а не -host-.

Autumn Leonard 15.02.2017 22:56

@AutumnLeonard: домен является хоста.

Lightness Races in Orbit 16.02.2017 03:28

@LightnessRacesinOrbit Не обязательно. support.suso.com/supki/…

Autumn Leonard 22.02.2017 17:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
159
9
256 259
18
Перейти к ответу Данный вопрос помечен как решенный

Ответы 18

Ответ принят как подходящий

Проверьте 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-адресов.

Единственное, чего не делает parse_url (), - это только возвращать домен. Если вы добавите www.google.com или www.google.co.uk, он также вернет хост. Есть предложения по этому поводу?

Gavin M. Roy 30.12.2008 03:40

@Crad, stackoverflow.com/questions/8272805/…

ilhan 26.11.2011 01:22
parse_url не обрабатывает поддомены, но Purl обрабатывает: github.com/jwage/purl
Damien 18.01.2013 15:48
parse_url(), возможно, неправильно проанализирует URL-адреса с доменом, который содержит дефисы. Не удалось найти точных доказательств, но проверьте эта ошибка. FILTER_VALIDATE_URL внутренне использует parse_url().
XedinUnknown 01.07.2015 12:16

Или просто: print parse_url($url, PHP_URL_HOST)), если массив $parse вам ни для чего не нужен.

rybo111 24.08.2016 15:03

Не обрабатывает domain.eu, который является вполне допустимым доменом.

tftd 20.06.2017 18:21

@tftd - это потому, что parse_url ожидает передачи url, но domain.eu - это только часть имени домена / имени хоста URL-адреса. «parse_url анализирует URL-адрес и возвращает ассоциативный массив, содержащий любой из различных компонентов URL-адреса, которые присутствуют. Эта функция - не предназначено для проверки для данного URL-адреса ...»

ashleedawg 20.12.2018 00:42

От http://us3.php.net/manual/en/function.parse-url.php#93983

for some odd reason, parse_url returns the host (ex. example.com) as the path when no scheme is provided in the input url. So I've written a quick function to get the real host:

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 29.12.2009 14:02

Если я использую example.com, php отображает уведомление: Message: Undefined index: host Есть идеи, как это исправить?

Zim3r 23.12.2012 13:58

К сожалению, субдомен все еще включен в этот подход, см. Ваш пример №3.

jenlampton 27.11.2016 00:14

@ Zim3r Измените первую часть троицы на !empty($parseUrl['host']).

Demonslay335 01.01.2017 21:43

LOL, если у него нет схемы, это не URL-адрес.

miken32 02.01.2020 22:03

В вопросе упоминается, что www. также следует удалить, поэтому этот ответ неверен

Murilo 07.01.2021 03:44
$domain = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));

Это вернет google.com для http://google.com/ ... и http://www.google.com/ ...

потому что он все равно вернет сервер, если вы введете "server.google.com" или "www3.google.com" ...

patrick 13.12.2012 16:12

Не все субдомены являются www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com - вот несколько примеров.

rafark 15.12.2019 23:43

Вот код, который я сделал, что 100% находит только доменное имя, так как для учета требуются под-TLD Mozilla. Единственное, что вам нужно проверить, это то, как вы делаете кеш этого файла, чтобы вы не запрашивали 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 г., 08:00 BST, однако существует период резервирования для существующих клиентов, у которых уже есть .co.uk, .org.uk, .me.uk. , .net.uk, .ltd.uk или .plc.uk, чтобы заявить права на соответствующий домен .uk, который работает до 07:59 BST на 10 июн 2019 ". (Источник)

ashleedawg 20.12.2018 01:06

Код, который должен был работать на 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

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

github.com/leth/registered-domains-php это почти то же самое, что и вы
Murilo 07.01.2021 03:47

parse_url у меня не работал. Это только вернуло путь. Переход к основам с использованием php5.3 +:

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

Как правило, это будет работать очень хорошо, если входной 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

Вы можете передать 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'

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

MrWhite 25.04.2016 17:32

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

jenlampton 27.11.2016 00:34

Я отредактировал для вас:

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.

$domain = parse_url($url, PHP_URL_HOST);
echo implode('.', array_slice(explode('.', $domain), -2, 2))

не работает для google.co.uk/dhasjkdas/sadsdds/sdda/sdads.html

jenlampton 27.11.2016 00:33
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 27.11.2016 00:18

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

Rick 07.07.2019 16:31

Просто используйте, как показано ниже ...

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

Предполагается, что сервер - это URL-адрес, с которого вы хотите получить домен. Это не так.

Overcode 30.06.2015 23:42

Объединение ответов worldofjr и Аликс Аксель в одну небольшую функцию, которая будет обрабатывать большинство вариантов использования:

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 18.01.2017 19:28

Если вы хотите извлечь хост из строки 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'

Большое спасибо за это предложение. Я ненавижу добавлять еще одну библиотеку для того, что появляется было простой задачей, но потом я увидел эту цитату в их readme, примененную ко мне: «Все ошибаются. Разделение на '.' и использование последних двух элементов имеет большое значение, только если вы думаете о простых, например, доменах .com. Подумайте, например, о разборе forum.bbc.co.uk: наивный метод разделения, приведенный выше, даст вам «co» в качестве домена и «uk» в качестве TLD вместо "bbc" и "co.uk" соответственно ".

Demonslay335 01.01.2017 21:58

Результат разбиения точек на наши любимые домены .co.uk - это не то, что мы хотим, но на самом деле это правильный результат: co - это второй уровень, а uk - верхний уровень. Веб-мастера часто этого не осознают.

Chris 28.10.2017 01:06

Я добавляю этот ответ поздно, так как это ответ, который чаще всего всплывает в 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», он вернет null. Таким образом, он ожидает наличия протоколов (например, http или https).

Andy 15.02.2018 03:28

Я обнаружил, что решение @ philfreo (указанное на php.net) довольно хорошо для получения хорошего результата, но в некоторых случаях оно показывает сообщение 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

Пожалуйста, подумайте о замене принятого решения следующим:

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 Джереми Кендалла позволяет вам анализировать доменное имя из URL-адреса. Парсер имени хоста URI лиги также выполнит эту работу.

Привет, это хорошо, но не работает с IP-адресами. Тем не менее, отличная работа.

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

Другие вопросы по теме