Получить поддомен с URL-адреса
Получение субдомена из URL-адреса сначала легко.
http://www.domain.example
Отсканируйте первый период, затем верните все, что было после "http://"...
Затем вы помните
http://super.duper.domain.example
О. Итак, тогда вы думаете, хорошо, найдите последний период, верните слово и получите все раньше!
Затем вы помните
http://super.duper.domain.co.uk
И ты вернешься к квадрату. У кого-нибудь есть отличные идеи помимо хранения списка всех TLD?
Ответы
Ответ 1
У кого-нибудь есть отличные идеи, кроме хранения списка всех TLD?
Нет, потому что каждый TLD отличается тем, что считается субдоменом, доменом второго уровня и т.д.
Имейте в виду, что есть домены верхнего уровня, домены второго уровня и поддоменов. Технически говоря, все, кроме TLD, является поддоменом.
В примере domain.com.uk "домен" - это поддомен, "com" - это домен второго уровня, а "uk" - это TLD.
Таким образом, вопрос остается более сложным, чем на первый взгляд, и зависит от того, как управляется каждый TLD. Вам понадобится база данных всех TLD, которые включают в себя их конкретное разделение и то, что считается доменом второго уровня и поддоменом. Однако TLD не слишком много, поэтому этот список достаточно управляем, но собрать всю эту информацию нетривиально. Возможно, такой список уже есть.
Похоже, http://publicsuffix.org/ является одним из таких списков - все распространенные суффиксы (.com,.co.uk и т.д.) В списке, подходящем для поиска. Разобрать его все равно будет непросто, но, по крайней мере, вам не нужно вести список.
"Открытый суффикс" - это тот, под которым пользователи Интернета могут напрямую регистрировать имена. Некоторыми примерами общедоступных суффиксов являются ".com", ".co.uk" и "pvt.k12.wy.us". Public Suffix List - это список всех известных общедоступных суффиксов.
Публичный список суффиксов является инициативой фонда Mozilla. Он доступен для использования в любом программном обеспечении, но изначально был создан для удовлетворения потребностей производителей браузеров. Это позволяет браузерам, например:
- Избегайте использования "супер-куки", нарушающих конфиденциальность, для высокоуровневых суффиксов доменных имен
- Выделите наиболее важную часть доменного имени в пользовательском интерфейсе
- Точная сортировка записей истории по сайту
Просматривая список, вы видите, что это не тривиальная проблема. Я думаю, что список является единственным правильным способом сделать это...
Ответ 2
Как говорит Адам, это непросто, и в настоящее время единственным практическим способом является использование списка.
Даже тогда есть исключения - например, в .uk
имеется несколько доменов, которые немедленно действительны на этом уровне, которые не находятся в .co.uk
, поэтому они должны быть добавлены как исключения.
В настоящее время, как это делают основные браузеры, необходимо убедиться, что example.co.uk
не может установить Cookie для .co.uk
, который затем будет отправлен на любой другой сайт под .co.uk
.
Хорошей новостью является то, что уже существует список доступных http://publicsuffix.org/.
Там также есть работа в IETF, чтобы создать какой-то стандарт, позволяющий TLD объявлять, как выглядит их структура домена. Это немного сложно, хотя подобным .uk.com
, который работает, как будто это открытый суффикс, но не продается реестром .com
.
Ответ 3
Publicsuffix.org - это способ сделать. Существует множество реализаций для простого анализа содержимого файла данных данных publicsuffix:
Ответ 4
Как уже говорили Адам и Джон publicsuffix.org, это правильный путь. Но если по какой-либо причине вы не можете использовать этот подход, здесь эвристика основана на предположении, что работает для 99% всех доменов:
Существует одно свойство, которое отличает (не все, но почти все) "реальные" домены от поддоменов и TLD, а также запись DNS MX. Вы можете создать алгоритм, который выполняет поиск: Удалите части имени узла один за другим и запросите 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 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");
}
Ответ 5
Как уже говорилось, Public Suffix List - это единственный способ правильно разобрать домен. Для 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'
Ответ 6
Просто написал программу для этого в 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"}
Ответ 7
Для библиотеки 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
Ответ 8
Это не работает точно, но вы могли бы получить полезный ответ, пытаясь извлечь домен по частям и проверить ответ, т.е. получить " http://uk ', затем http://co.uk', затем http://domain.co.uk '. Когда вы получаете ответ без ошибок, у вас есть домен, а остальное - субдомен.
Иногда вам просто нужно попробовать:)
Edit:
Том Лейс указывает в комментариях, что некоторые домены настраиваются только на субдомене www, что дало бы нам неправильный ответ в вышеприведенном тесте. Хорошая точка зрения! Возможно, лучший подход состоял бы в том, чтобы проверить каждую часть с помощью http://www ', а также' http://'и посчитать хит либо в качестве хита для этот раздел доменного имени? Нам все равно не хватает некоторых "альтернативных" аранжировок, таких как "web.domain.com", но я не натолкнулся на это некоторое время:)
Ответ 9
Использовать URIBuilder
затем получить атрибут URIBUilder.host
разделите его на массив на "."
теперь у вас есть массив с разделом домена.
Ответ 10
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;
}
Ответ 11
Я только что написал библиотеку objc: https://github.com/kejinlu/KKDomain
Ответ 12
Вы можете использовать этот lib tld.js: JavaScript API для работы со сложными именами доменов, субдоменами и URI.
tldjs.getDomain('mail.google.co.uk');
// -> 'google.co.uk'
Если вы получаете корневой домен в браузере. Вы можете использовать этот lib 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 сложно.
Ответ 13
Если вы хотите извлечь субдомены и/или домены из произвольного списка URL-адресов, этот скрипт на python может быть полезен. Будьте осторожны, это не идеально. Это сложная проблема для решения в целом, и это очень полезно, если у вас есть белый список доменов, которые вы ожидаете.
- Получить домены верхнего уровня от publicsuffix.org
import requests
url = 'https://publicsuffix.org/list/public_suffix_list.dat'
page = requests.get(url)
domains = []
for line in page.text.splitlines():
if line.startswith('//'):
continue
else:
domain = line.strip()
if domain:
domains.append(domain)
domains = [d[2:] if d.startswith('*.') else d for d in domains]
print('found {} domains'.format(len(domains)))
- Построить регулярное выражение
import re
_regex = ''
for domain in domains:
_regex += r'{}|'.format(domain.replace('.', '\.'))
subdomain_regex = r'/([^/]*)\.[^/.]+\.({})/.*$'.format(_regex)
domain_regex = r'([^/.]+\.({}))/.*$'.format(_regex)
- Использовать регулярное выражение в списке URL
FILE_NAME = '' # put CSV file name here
URL_COLNAME = '' # put URL column name here
import pandas as pd
df = pd.read_csv(FILE_NAME)
urls = df[URL_COLNAME].astype(str) + '/' # note: adding / as a hack to help regex
df['sub_domain_extracted'] = urls.str.extract(pat=subdomain_regex, expand=True)[0]
df['domain_extracted'] = urls.str.extract(pat=domain_regex, expand=True)[0]
df.to_csv('extracted_domains.csv', index=False)
Ответ 14
Список общих суффиксов (.co.uk,.com, et cetera), чтобы вырезать вместе с http://, а затем вы будете иметь только "sub.domain", а не " http://sub.domain.suffix", или, по крайней мере, то, что я, вероятно, сделаю.
Самая большая проблема - список возможных суффиксов. В конце концов, много.
Ответ 15
Вы можете взглянуть на мое решение на
http://www.nimeshdotnet.info/post/Getting-Subdomain-from-an-URL-in-Net.aspx
Ответ 16
Если вы быстро взглянете на список publicsuffix.org, вы можете сделать разумное приближение, удалив последние три сегмента ( "сегмент" здесь означает раздел между двумя точками) из доменов, где конечный сегмент равен двум длинными символами, исходя из предположения, что это код страны и будет далее разделен. Если конечный сегмент является "нами", а второй-последний сегмент также является двумя символами, удалите последние четыре сегмента. Во всех остальных случаях удалите последние два сегмента. например:.
"пример" не два символа, поэтому удалите "domain.example", оставив "www"
"example" не является двумя символами, поэтому удалите "domain.example", оставив "super.duper"
"uk" - это два символа (но не "мы" ), поэтому удалите "domain.co.uk", оставив "super.duper"
"us" - это два символа и "мы", плюс "wy" также два символа, поэтому удалите "pvt.k12.wy.us", оставив "foo".
Обратите внимание, что, хотя это работает для всех примеров, которые я видел в ответах до сих пор, он остается только разумным приближением. Это не совсем правильно, хотя я подозреваю, что это примерно так же близко, как вы, вероятно, получите, не сделав/не получив фактический список для использования для справки.