Идти туда, где не работает PHP parse_url () - Разбор только домена - PullRequest
12 голосов
/ 30 декабря 2008

PHP parse_url () имеет поле хоста, которое включает полный хост. Я ищу самый надежный (и наименее затратный) способ вернуть только домен и TLD.

Приведены примеры:

Я ищу только google.com или google.co.uk . Я рассмотрел таблицу действительных ДВУ / суффиксов и допускаю только одно и то же слово. Вы бы сделали это по-другому? Кто-нибудь знает о предварительно консервированном действующем REGEX для такого рода вещей?

Ответы [ 8 ]

17 голосов
/ 30 декабря 2008

Как насчет чего-то подобного?

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

6 голосов
/ 30 декабря 2008

В настоящее время единственный «правильный» способ сделать это - использовать список, который поддерживается на http://publicsuffix.org/

Кстати, этот вопрос также в значительной степени дублирует:

В IETF предпринимаются усилия по стандартизации, направленные на то, чтобы DNS-методы объявляли, используется ли определенный узел в дереве DNS для «открытых» регистраций, но они находятся на ранних стадиях разработки. Все популярные не-IE браузеры используют список publicsuffix.org.

4 голосов
/ 02 октября 2013

Существует также очень хороший порт модуля tldextract в Python http://w -shadow.com / blog / 2012/08/28 / tldextract - это выходит за рамки parse_url и позволяет фактически получить домен / tld out, без субдомена.

С сайта модуля:

$components = tldextract('http://www.bbc.co.uk');
echo $components->subdomain; // www
echo $components->domain;    // bbc
echo $components->tld;       // co.uk
1 голос
/ 01 июля 2016

Вам нужен пакет, который использует Публичный список суффиксов , только таким образом вы сможете правильно извлечь домены с доменами верхнего уровня двух, третьего уровня (co.uk, a.bg, b.bg и т. Д.). ) и многоуровневых поддоменов. Regex, parse_url () или строковые функции никогда не дадут абсолютно правильный результат.

Я рекомендую использовать Экстракт ДВУ . Вот пример кода:

$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'
1 голос
/ 30 декабря 2008

Выкопал это из соответствующего поста, для идеи ведения таблицы: http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/src/effective_tld_names.dat?raw=1

Я бы предпочел этого не делать.

0 голосов
/ 01 января 2009

Существует очень простое решение:

function get_domain($url) {
  $pieces = parse_url($url);
  return array_pop(explode('.', $pieces['host'], 2));
}

Конечно, это будет работать?

0 голосов
/ 30 декабря 2008

Просто доказательство, предполагая, что разрешенные данные запоминаются в хеш. Код может быть значительно сокращен.

<?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
    }
?>
0 голосов
/ 30 декабря 2008

Конечно, это зависит от вашего конкретного случая использования, но, вообще говоря, я бы не использовал поиск таблиц для TLD. Новые TLD выходят, и вы обычно не хотите поддерживать их где-либо. Просто спросите меня, как часто мое firstname@lastname.name отклоняется из-за близорукости.

Полагаю, я мог бы помочь лучше, если бы знал, почему ты не хочешь www? Вам это нужно для электронной почты? В таких случаях вы можете запросить записи MX, чтобы убедиться, что он (в конце концов) принимает почту.

Вы также можете найти справку по функциям PHP, связанным с DNS-записями, чтобы узнать больше информации о них, см., Например, http://php.net/dns_get_record.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...