Переход туда, где отсутствует PHP parse_url(), - анализ только домена
PHP parse_url() имеет поле хоста, которое включает полный хост. Я ищу самый надежный (и наименее дорогостоящий) способ только вернуть домен и TLD.
Учитывая примеры:
Я ищу только google.com или google.co.uk. Я рассматривал таблицу действительных TLD/суффиксов и допускал только те и одно слово. Сделали бы это по-другому? Кто-нибудь знает о заранее подготовленном действительном REGEX для такого рода вещей?
Ответы
Ответ 1
Как насчет чего-то подобного?
function getDomain($url) {
$pieces = parse_url($url);
$domain = isset($pieces['host']) ? $pieces['host'] : '';
if (preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)) {
return $regs['domain'];
}
return false;
}
Будет извлечено доменное имя с помощью классического parse_url
, а затем найдите действительный домен без какого-либо субдомена (www является субдоменом). Не будет работать над такими вещами, как "localhost". Вернет false, если он ничего не соответствует.
//Редактировать:
Попробуйте:
echo getDomain('http://www.google.com/test.html') . '<br/>';
echo getDomain('https://news.google.co.uk/?id=12345') . '<br/>';
echo getDomain('http://my.subdomain.google.com/directory1/page.php?id=abc') . '<br/>';
echo getDomain('https://testing.multiple.subdomain.google.co.uk/') . '<br/>';
echo getDomain('http://nothingelsethan.com') . '<br/>';
И он должен вернуться:
google.com
google.co.uk
google.com
google.co.uk
nothingelsethan.com
Конечно, он ничего не вернет, если он не пройдет через parse_url
, поэтому убедитесь, что он хорошо сформирован URL.
//Добавление:
Альнитак прав. Решение, представленное выше, будет работать в большинстве случаях, но не обязательно для всех, и их необходимо поддерживать, чтобы убедиться, например, что они не являются новым TLD с символами .morethan6 и т.д. Единственным надежным способом извлечения домена является использование сохраненного списка, такого как http://publicsuffix.org/. Это более болезненно сначала, но проще и надежнее в долгосрочной перспективе. Вам нужно убедиться, что вы понимаете плюсы и минусы каждого метода и то, как он соответствует вашему проекту.
Ответ 2
В настоящее время единственный "правильный" способ сделать это - использовать список, который поддерживается в http://publicsuffix.org/
Кстати, этот вопрос также в значительной степени дублируется:
В IETF есть попытки стандартизации, рассматривающие методы DNS, объявляющие, что конкретный node в дереве DNS используется для "публичных" регистраций, но они находятся на ранних стадиях разработки. Все популярные браузеры, отличные от IE, используют список publicsuffix.org.
Ответ 3
Существует также очень хороший порт Python tldextract module http://w-shadow.com/blog/2012/08/28/tldextract - это выходит за рамки parse_url и позволяет фактически получить домен/без субдомена.
С веб-сайта модуля:
$components = tldextract('http://www.bbc.co.uk');
echo $components->subdomain; // www
echo $components->domain; // bbc
echo $components->tld; // co.uk
Ответ 4
Извлеките это из связанного сообщения, за идею сохранения таблицы: http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/src/effective_tld_names.dat?raw=1
Я бы не хотел этого делать.
Ответ 5
Конечно, это зависит от вашего конкретного варианта использования, но, вообще говоря, я бы не использовал поиск таблицы для TLD. Появляются новые TLD, и вы обычно не хотите их поддерживать нигде. Просто спросите меня, как часто мое имя [email protected] было отклонено из-за близорукости.
Думаю, я мог бы помочь лучше, если бы знал, почему вы не хотите www? Вам это нужно для электронных писем? Вы можете запросить записи MX в таких случаях, чтобы проверить (в конечном итоге) прием писем.
Вы также можете найти помощь с функциями PHP, связанными с записями DNS, чтобы узнать больше о них, см. http://php.net/dns_get_record.
Ответ 6
Просто доказательство, предполагая, что разрешенные tlds запомнены в хэш.
Код может быть значительно сокращен.
<?php
$urlCompoments=parse_url($theUrl);
$chunk=explode('.',$urlComponents['host']);
$tldIndex = count($chunk-1); // assume last chunk is tld
$maxTldLen = 2; // assuming a tld can be in the form .com or .co.uk
$cursor=1;
$found=false;
while(($cursor<=$maxTldLen) or $found) {
$tls = implode('.',array_slice($chunk, -$cursor));
$found=isset($tldSuffixesAllowed[$tld]);
$cursor++;
}
if ($found){
$tld=implode('.',array_slice($chunk, -$cursor));
} else {
// domain not recognized, do wathever you want
}
?>
Ответ 7
Вам нужен пакет, который использует Public Suffix List, только таким образом вы можете корректно извлекать домены с двумя доменами третьего уровня (co.uk, a.bg, b.bg и т.д.) и многоуровневые субдомены. Regex, parse_url() или строковые функции никогда не приведут к абсолютно правильному результату.
Я рекомендую использовать TLD Extract. Вот пример кода:
$extract = new LayerShifter\TLDExtract\Extract();
$result = $extract->parse('http://www.google.co.uk/foo');
$result->getSubdomain(); // will return (string) 'www'
$result->getHostname(); // will return (string) 'google'
$result->getSuffix(); // will return (string) 'co.uk'
$result->getRegistrableDomain(); // will return (string) 'google.co.uk'
Ответ 8
Существует очень простое решение:
function get_domain($url) {
$pieces = parse_url($url);
return array_pop(explode('.', $pieces['host'], 2));
}
Неужели это сработает?