Разбор домена с URL в PHP

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

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

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

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

С 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 

Код, который должен был работать на 100%, по-видимому, не сократил его для меня, я немного исправил этот пример, но нашел код, который не помогал, и проблемы с ним. поэтому я изменил его на несколько функций (чтобы сохранить запрос на список из mozilla все время и удалить систему cahce). Это было протестировано против набора из 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: exmaple.com echo domain('www.example.uk.com') //outputs: exmaple.uk.com echo domain('www.example.fr') //outputs: exmaple.fr 

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

 function get_domain($url = SITE_URL) { preg_match("/[a-z0-9\-]{1,63}\.[az\.]{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 

Если вы хотите извлечь хост из строки http://google.com/dhasjkdas/sadsdds/sdda/sdads.html , использование parse_url () является приемлемым решением для вас.

Но если вы хотите извлечь домен или его части, вам нужен пакет, в котором используется Public Suffix List . Да, вы можете использовать строковые функции arround parse_url (), но иногда это приводит к некорректным результатам.

Я рекомендую TLDExtract для разбора домена, вот пример кода, который показывает diff:

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

Вот код, который я сделал, что 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]; } 

Вы можете передать 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' 
 $domain = parse_url($url, PHP_URL_HOST); echo implode('.', array_slice(explode('.', $domain), -2, 2)) 

Я обнаружил, что решение @ 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 не работал для меня. Он только вернул путь. Переход к основам с использованием php5.3 +:

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

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

 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.

Проверьте parse_url ()

Вот мой искатель, основанный на приведенных выше ответах.

  1. Внедрение класса (мне нравится Obj 🙂
  2. он использует Curl поэтому мы можем использовать HTTP-аутентификацию
  3. это только обходная ссылка, которая принадлежит начальному домену URL
  4. он печатает код ответа HTTP-заголовка (полезно для проверки проблем на сайте)

КЛАСС КРАСНОГО КЛАССА

 class crawler { protected $_url; protected $_depth; protected $_host; public function __construct($url, $depth = 5) { $this->_url = $url; $this->_depth = $depth; $parse = parse_url($url); $this->_host = $parse['host']; } public function run() { $this->crawl_page($this->_url, $this->_depth = 5); } public function crawl_page($url, $depth = 5) { static $seen = array(); if (isset($seen[$url]) || $depth === 0) { return; } $seen[$url] = true; list($content, $httpcode) = $this->getContent($url); $dom = new DOMDocument('1.0'); @$dom->loadHTML($content); $this->processAnchors($dom, $url, $depth); ob_end_flush(); echo "CODE::$httpcode, URL::$url <br>"; ob_start(); flush(); // echo "URL:", $url, PHP_EOL, "CONTENT:", PHP_EOL, $dom->saveHTML(), PHP_EOL, PHP_EOL; } public function processAnchors($dom, $url, $depth) { $anchors = $dom->getElementsByTagName('a'); foreach ($anchors as $element) { $href = $element->getAttribute('href'); if (0 !== strpos($href, 'http')) { $path = '/' . ltrim($href, '/'); if (extension_loaded('http')) { $href = http_build_url($url, array('path' => $path)); } else { $parts = parse_url($url); $href = $parts['scheme'] . '://'; if (isset($parts['user']) && isset($parts['pass'])) { $href .= $parts['user'] . ':' . $parts['pass'] . '@'; } $href .= $parts['host']; if (isset($parts['port'])) { $href .= ':' . $parts['port']; } $href .= $path; } } // Crawl only link that belongs to the start domain if (strpos($href, $this->_host) !== false) $this->crawl_page($href, $depth - 1); } } public function getContent($url) { $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); /* Get the HTML or whatever is linked in $url. */ $response = curl_exec($handle); /* Check for 404 (file not found). */ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if ($httpCode == 404) { /* Handle 404 here. */ } curl_close($handle); return array($response, $httpCode); } } // USAGE $startURL = 'http://YOUR_START_ULR'; $depth = 2; $crawler = new crawler($startURL, $depth); $crawler->run(); 

Я добавляю этот ответ позже, так как это ответ, который чаще всего появляется в 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)); } 

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

Объединяя ответы 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 

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

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