Получить поддомен из URL-адреса
получение поддомена из URL-адреса сначала звучит просто.
http://www.domain.example
сканирование в течение первого периода, а затем вернуть все, что пришло после "http://" ...
затем вы помните
http://super.duper.domain.example
Ох. Итак, вы думаете: хорошо, найдите последний период, вернитесь на слово и получите все раньше!
затем вы помните
http://super.duper.domain.co.uk
и вы вернулись к квадрату один. У кого-нибудь есть отличные идеи, кроме хранения списка всех дву?
14 ответов:
у кого-нибудь есть отличные идеи, к тому же хранение списка всех доменов?
нет, потому что каждый TLD отличается от того, что считается поддоменом, доменом второго уровня и т. д.
имейте в виду, что существуют домены верхнего уровня, домены второго уровня и поддомены. Технически говоря, все, кроме TLD, является поддоменом.
в домене.ком.пример Великобритании, домен является поддоменом, com-это домен второго уровня, и Великобритания дву.
таким образом, вопрос остается более сложным, чем на первый взгляд, и это зависит от того, как управляется каждый TLD. Вам понадобится база данных всех дву, которые включают их конкретное разделение, а также то, что считается доменом второго уровня и поддоменом. Однако существует не так много дву, поэтому список достаточно управляем, но сбор всей этой информации не является тривиальным. Возможно, такой список уже существует.
похоже, http://publicsuffix.org/ есть один такой список - все общие суффиксы (. com, .co.uk, etc) в списке, подходящем для поиска. Это все еще не будет легко разобрать его, но по крайней мере вам не нужно поддерживать список.
"публичный суффикс" - это тот, под которым Пользователи интернета могут напрямую зарегистрироваться имена. Некоторые примеры публичных суффиксы ".ком", ".ко.Великобритания" и "pvt.k12.wy.us". общественный суффикс Список-это список всех известных общественности суффиксы.
публичный список суффиксов является инициатива Фонда Mozilla. Он доступен для использования в любом программное обеспечение, но изначально было создано для удовлетворения потребностей браузера мировые производители. Это позволяет браузерам, например:
- избегайте конфиденциальности-вредные "суперкуки" устанавливаются для высокоуровневые суффиксы доменных имен
- выделите наиболее важную часть доменного имени в пользователя интерфейс
- точно история рода записи по сайту
просматривая список, вы можете увидеть, что это не тривиальная проблема. Я думаю, что список является единственным правильным способом для достижения этой цели...
Адам
даже тут есть исключения - например в
.uk
есть несколько доменов, которые действительны сразу на этом уровне, которые не находятся в.co.uk
, поэтому они должны быть добавлены в качестве исключений.это в настоящее время, как основные браузеры делают это - это необходимо, чтобы убедиться, что
example.co.uk
не удается установить Cookie для.co.uk
который затем будет отправлен на любой другой сайт под.co.uk
.хорошая новость заключается в том, что уже есть список доступных в http://publicsuffix.org/.
есть также некоторые работы в IETF чтобы создать какой-то стандарт, позволяющий дву объявлять, как выглядит их доменная структура. Это немного сложнее, хотя и подобными
.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 / browser-root-domain.
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.uk,. com, et cetera), чтобы раздеться вместе с http:// и тогда у вас будет только "sub.домен" для работы вместо"http://sub.домен.суффикс
бросив быстрый взгляд на publicsuffix.org список, похоже, что вы можете сделать разумное приближение, удалив последние три сегмента ("сегмент" здесь означает раздел между двумя точками) из доменов, где последний сегмент имеет два символа длиной, исходя из предположения, что это код страны и будет далее подразделяться. Если последний сегмент-это "us", а предпоследний сегмент-это также два символа, удалите последние четыре сегмента. Во всех остальных случаях удалите заключительные два сегмента. например:
"пример" - это не два символа, поэтому удалите "домен".пример", оставив "ВСП"
"пример" - это не два символа, поэтому удалите "домен".пример", оставив "супер.пупер"
" uk " - это два персонажи (но не "мы"), так что уберите "domain.co.uk", уходя " супер.пупер"
"нам" - это два символа, и это "мы", плюс "Вайоминг" тоже два символа, чтобы удалить "ПВТ.К12.Вайоминг.нас", оставив "фу".
обратите внимание, что, хотя это работает для всех примеров, которые я видел в ответах, осталось только разумное приближение. Это не совсем правильно, хотя я подозреваю, что это примерно так же близко как вы, вероятно, получите без создания/получения фактического списка для использования Для справки.