Получить поддомен из URL-адреса

получение поддомена из URL-адреса сначала звучит легко.

http://www.domain.example

сканирование в течение первого периода, а затем вернуть все, что пришло после " http://"...

затем вы помните

http://super.duper.domain.example

Ох. Тогда ты думаешь: "ладно, найди последний урок, вернись на пару слов назад и получи все раньше!"

затем вы помните

http://super.duper.domain.co.uk

и вы вернулись к началу. У кого-нибудь есть отличные идеи, кроме хранения списка всех TLDs?

14 ответов


у кого-нибудь есть отличные идеи, к тому же хранение списка всех доменов?

нет, потому что каждый TLD отличается от того, что считается поддоменом, доменом второго уровня и т. д.

имейте в виду, что существуют домены верхнего уровня, домены второго уровня и поддомены. Технически говоря, все, кроме TLD, является поддоменом.

в домене.com.пример Великобритании, домен является поддоменом, com-домен второго уровня, а uk - дву.

таким образом, вопрос остается более сложным, чем на первый взгляд, и это зависит от того, как управляется каждый TLD. Вам понадобится база данных всех дву, которые включают их конкретное разделение, и то, что считается доменом второго уровня и поддоменом. Однако дву не так уж много, так что список вполне управляемый, но сбор всей этой информации не тривиален. Возможно, такой список уже имеется.

похоже, http://publicsuffix.org/ есть один такой список - все общие суффиксы (.com,.co.uk, etc) в списке, подходящем для поиска. Его все равно будет нелегко разобрать, но, по крайней мере, вам не нужно поддерживать список.

" публичный суффикс " - это тот, под которым Пользователи интернета могут напрямую зарегистрироваться имена. Некоторые примеры общественных суффиксы-это ".com",".co.Великобритания " и "pvt.К12.wy.мы". Публичный Суффикс List-это список всех известных общественности суффиксы.

список публичных суффиксов инициатива Фонда Mozilla. Он доступен для использования в любом программное обеспечение, но было первоначально создано для удовлетворения потребностей браузера мировые производители. Это позволяет браузерам, например:

  • избегайте конфиденциальности-повреждение "supercookies" устанавливается для суффиксы доменных имен высокого уровня
  • выделите наиболее важную часть доменного имени пользователя интерфейс
  • точно история рода записи по сайту

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


как говорит Адам, это непросто, и в настоящее время единственный практический способ-использовать список.

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

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

хорошая новость заключается в том, что список уже доступен по адресу http://publicsuffix.org/.

есть также некоторые работы в IETF чтобы создать какой-то стандарт, позволяющий TLDs объявлять, как выглядит их доменная структура. Это немного сложно, хотя и подобными .uk.com, который управляется как если бы это был публичный суффикс, но не продается .com реестра.


Publicsuffix.org кажется, так и надо. Существует множество реализаций, чтобы легко анализировать содержимое файла данных publicsuffix:


Как уже сказали Адам и Иоанн publicsuffix.org это правильный путь. Но, если по какой-либо причине вы не можете использовать этот подход, вот эвристика, основанная на предположении, которое работает для 99% всех доменов:

есть одно свойство, которое отличает (не все, но почти все) "реальные" Домены от поддоменов и дву, и это MX-запись DNS. Вы можете создать алгоритм, который ищет это: удалите части имени хоста по одному и запросите DNS, пока вы не найдете запись MX. Пример:

super.duper.domain.co.uk => no MX record, proceed
duper.domain.co.uk       => no MX record, proceed
domain.co.uk             => MX record found! assume that's the domain

вот пример в php:

function getDomainWithMX($url) {
    //parse hostname from URL 
    //http://www.example.co.uk/index.php => www.example.co.uk
    $urlParts = parse_url($url);
    if ($urlParts === false || empty($urlParts["host"])) 
        throw new InvalidArgumentException("Malformed URL");

    //find first partial name with MX record
    $hostnameParts = explode(".", $urlParts["host"]);
    do {
        $hostname = implode(".", $hostnameParts);
        if (checkdnsrr($hostname, "MX")) return $hostname;
    } while (array_shift($hostnameParts) !== null);

    throw new DomainException("No MX record found");
}

просто написал программу для этого в clojure на основе информации из publicsuffix.org:

https://github.com/isaksky/url_dom

например:

(parse "sub1.sub2.domain.co.uk") 
;=> {:public-suffix "co.uk", :domain "domain.co.uk", :rule-used "*.uk"}

для библиотеки C (с генерацией таблицы данных в Python) я написал http://code.google.com/p/domain-registry-provider/ который и быстр и космос эффективный.

библиотека использует ~30kB для таблиц данных и ~10kB для кода C. Нет никаких накладных расходов при запуске, так как таблицы создаются во время компиляции. Вижу http://code.google.com/p/domain-registry-provider/wiki/DesignDoc для более подробной информации.

чтобы лучше понять таблицу код генерации (Python), начните здесь: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/registry_tables_generator/registry_tables_generator.py

чтобы лучше понять API C, см.: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/domain_registry/domain_registry.h


Как уже было сказано Список Публичных Суффиксов это только один способ правильно проанализировать домен. Для PHP вы можете попробовать TLDExtract. Вот пример кода:

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

$result = $extract->parse('super.duper.domain.co.uk');
$result->getSubdomain(); // will return (string) 'super.duper'
$result->getSubdomains(); // will return (array) ['super', 'duper']
$result->getHostname(); // will return (string) 'domain'
$result->getSuffix(); // will return (string) 'co.uk'

Это не работает точно, но вы могли бы получить полезный ответ, пытаясь получить домен по частям и проверить ответ, т. е. fetch'http://uk', затем'http://co.uk', затем'http://domain.co.uk'. Когда вы получаете ответ без ошибок, у вас есть домен, а остальное-поддомен.

иногда вы просто должны попробовать это :)

Edit:

том Лейс указывает в комментарии, что некоторые домены настроены только на субдомене www, что дало бы нам неправильный ответ в приведенном выше тесте. Хорошая мысль! Возможно, лучшим подходом было бы проверить каждую часть с помощью 'http://www', а также " http://", и считать попадание либо как попадание для этого раздела доменного имени? Мы все еще будем упускать некоторые "альтернативные" договоренности, такие как "web.domain.com', но я не сталкивался с одним из них в течение некоторого времени:)


используйте URIBuilder тогда получите URIBUilder.атрибут хоста разбейте его на массив по "." теперь у вас есть массив с разделенным доменом.


echo tld('http://www.example.co.uk/test?123'); // co.uk

/**
 * http://publicsuffix.org/
 * http://www.alandix.com/blog/code/public-suffix/
 * http://tobyinkster.co.uk/blog/2007/07/19/php-domain-class/
 */
function tld($url_or_domain = null)
{
    $domain = $url_or_domain ?: $_SERVER['HTTP_HOST'];
    preg_match('/^[a-z]+:\/\//i', $domain) and 
        $domain = parse_url($domain, PHP_URL_HOST);
    $domain = mb_strtolower($domain, 'UTF-8');
    if (strpos($domain, '.') === false) return null;

    $url = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';

    if (($rules = file($url)) !== false)
    {
        $rules = array_filter(array_map('trim', $rules));
        array_walk($rules, function($v, $k) use(&$rules) { 
            if (strpos($v, '//') !== false) unset($rules[$k]);
        });

        $segments = '';
        foreach (array_reverse(explode('.', $domain)) as $s)
        {
            $wildcard = rtrim('*.'.$segments, '.');
            $segments = rtrim($s.'.'.$segments, '.');

            if (in_array('!'.$segments, $rules))
            {
                $tld = substr($wildcard, 2);
                break;
            }
            elseif (in_array($wildcard, $rules) or 
                    in_array($segments, $rules))
            {
                $tld = $segments;
            }
        }

        if (isset($tld)) return $tld;
    }

    return false;
}

Я только что написал библиотеку objc:https://github.com/kejinlu/KKDomain


вы можете использовать этот lib tld.JS: JavaScript API для работы со сложными доменными именами, поддоменами и URI.

tldjs.getDomain('mail.google.co.uk');
// -> 'google.co.uk'

Если вы получаете корневой домен в браузере. Вы можете использовать этот Либ AngusFu / браузер-корневой домен.

var KEY = '__rT_dM__' + (+new Date());
var R = new RegExp('(^|;)\s*' + KEY + '=1');
var Y1970 = (new Date(0)).toUTCString();

module.exports = function getRootDomain() {
  var domain = document.domain || location.hostname;
  var list = domain.split('.');
  var len = list.length;
  var temp = '';
  var temp2 = '';

  while (len--) {
    temp = list.slice(len).join('.');
    temp2 = KEY + '=1;domain=.' + temp;

    // try to set cookie
    document.cookie = temp2;

    if (R.test(document.cookie)) {
      // clear
      document.cookie = temp2 + ';expires=' + Y1970;
      return temp;
    }
  }
};

использование cookie сложно.


список общих суффиксов (.co.Великобритания .com и т. д.), Чтобы удалить вместе с http://, и тогда у вас будет только "sub.домен "для работы вместо"http://sub.домен.суффикс

самая большая проблема-это список возможных суффиксов. есть много, в конце концов.


бросив быстрый взгляд на publicsuffix.org список, похоже, что вы можете сделать разумное приближение, удалив последние три сегмента ("сегмент" здесь означает раздел между двумя точками) из доменов, где конечный сегмент имеет два символа, исходя из предположения, что это код страны и будет далее подразделен. Если конечный сегмент-"мы", а предпоследний сегмент-также два символа, удалите последние четыре сегмента. Во всех остальных случаях удалите последние два сегмента. например:

"пример" - это не два символа, поэтому удалите "домен".пример", оставив "ВСП"

"пример" - это не два символа, поэтому удалите "домен".пример", оставив "супер.пупер"

" uk " - это два символы (но не "мы"), поэтому удалите "домен".co.Великобритания", оставив " супер.пупер"

" us "- это два символа и "us", плюс" wy "также два символа, поэтому удалите" pvt.К12.wy.нас", оставив "фу".

обратите внимание, что, хотя это работает для всех примеров, которые я видел в ответах, осталось только разумное приближение. Это не совсем правильно, хотя я подозреваю, что это примерно так же близко поскольку вы, вероятно, получите без создания/получения фактического списка для использования Для справки.