Извлечь основное доменное имя из заданного URL

Я использовал следующее, чтобы извлечь домен из URL-адреса: (Это тестовые примеры)

String regex = "^(ww[a-zA-Z0-9-]{0,}\\.)";
ArrayList<String> cases = new ArrayList<String>();
cases.add("www.google.com");
cases.add("ww.socialrating.it");
cases.add("www-01.hopperspot.com");
cases.add("wwwsupernatural-brasil.blogspot.com");
cases.add("xtop10.net");
cases.add("zoyanailpolish.blogspot.com");

for (String t : cases) {  
    String res = t.replaceAll(regex, "");  
}

Я могу получить следующие результаты:

google.com
hopperspot.com
socialrating.it
blogspot.com
xtop10.net
zoyanailpolish.blogspot.com

Первые четыре случая хороши. Последний не годится. Я хочу: blogspot.com для последнего, но он дает zoyanailpolish.blogspot.com. Что я делаю неправильно?


person chnet    schedule 27.08.2011    source источник
comment
Похоже, регулярные выражения в этот пост может вам помочь =)   -  person Josh Darnell    schedule 28.08.2011
comment
Тогда не добавляйте в выкройку эти глупые вуалубу. Если все, что вам нужно, это s/^[^.]+\.//, я предлагаю вам это сделать.   -  person tchrist    schedule 28.08.2011
comment
Однако не совсем понятно, чего вы хотите. Вы пытаетесь удалить первый компонент всегда, или все компоненты, кроме того, который находится непосредственно перед TLD, или первый, только если он начинается с ww или ....?   -  person Ray Toal    schedule 28.08.2011
comment
Это не только замена «ww». Я добавил новый пример выше. Например, xtop10.net, я хочу: xtop10.net. Хотя zoyanailpolish.blogspot.com должен быть blogspot.com   -  person chnet    schedule 28.08.2011
comment
to @tchrist, я думаю, ваше предложение - это приложение в vim. Но я хочу другого. Я не просто хочу заменить первую ww. В некоторых случаях, например, xtop10.net. Я хочу xtop10.net. Но ваш метод вернет net.   -  person chnet    schedule 28.08.2011
comment
Другими словами, вам нужен основной домен, а не поддомены. Правильный?   -  person James P.    schedule 28.08.2011
comment
Вы до сих пор не объяснили, чего хотите. Теперь похоже, что вам нужно просто разделить на точку и сохранить последние два возвращенных элемента.   -  person tchrist    schedule 28.08.2011
comment
Как насчет таких доменов, как example.com.tw и example.co.uk?   -  person BalusC    schedule 28.08.2011
comment
к @James Poulson, верно. Я хочу основной домен, а не поддомены   -  person chnet    schedule 28.08.2011
comment
к @BalusC, в ваших случаях. Я предпочитаю вернуться без изменений. Тем не менее, он возвращает example.com.tw и example.co.uk.   -  person chnet    schedule 28.08.2011
comment
Не забывайте, что в URL разрешены '-' и другие символы. (Подумайте за пределами ASCII)   -  person user823959    schedule 28.08.2011
comment
Тогда не делайте этого с помощью жесткого регулярного выражения. Использовать регулярное выражение для такого рода проблем просто нелепо. Разделить по точкам в массив. Подсчитайте детали. Убедитесь, что вторая последняя часть не равна ‹= 3 символам и / или начинается с co (возможно, есть другие ccTLD, которые вы хотели бы сопоставить). Возьмите последние два или три предмета в зависимости от результата и снова соедините их в точку.   -  person BalusC    schedule 28.08.2011
comment
к @BalusC, верно. Я согласен с тобой. Что значит вторая последняя часть не ‹= 3? Не могли бы вы объяснить больше?   -  person chnet    schedule 28.08.2011
comment
BalusC, вероятно, имеет в виду количество символов в части url. Регулярное выражение - это круто, но вам, вероятно, следует отказаться от него как от инструмента в пользу чего-то другого, если выражение становится слишком сложным.   -  person James P.    schedule 28.08.2011
comment
Как вы определяете, является ли что-то «основным доменом» или нет? foo.bar.com, foo.bar.co.uk и foo.bar.pvt.k12.wy.us не похожи друг на друга. Как вы решите опустить только foo, но останавливаться на bar в каждом из них, если вы получите разное количество точек?   -  person tchrist    schedule 28.08.2011
comment
к @tchrist, верно. Я не могу рассматривать так много возможностей.   -  person chnet    schedule 28.08.2011


Ответы (7)


Как было предложено BalusC и другими, наиболее практичным решением было бы получить список TLD (см. Этот список), сохраните их в файл, загрузите и затем определите, какой TLD используется данной строкой URL. Оттуда вы можете составить основное доменное имя следующим образом:

    String url = "zoyanailpolish.blogspot.com";

    String tld = findTLD( url ); // To be implemented. Add to helper class ?

    url = url.replace( "." + tld,"");  

    int pos = url.lastIndexOf('.');

    String mainDomain = "";

    if (pos > 0 && pos < url.length() - 1) {
        mainDomain = url.substring(pos + 1) + "." + tld;
    }
    // else: Main domain name comes out empty

Детали реализации оставлены на ваше усмотрение.

person James P.    schedule 27.08.2011
comment
пользователю @James Poulson, спасибо. извините, каков результат вашего примера? Я не совсем понял. Сначала он удаляет tld, а затем добавляет его. Итак, каков окончательный результат? - person chnet; 28.08.2011
comment
Нет вывода, так как это псевдокод. Необходимо создать текстовый файл со списком TLD (TLD можно найти по ссылке в Википедии), их необходимо прочитать в структуре данных и ввести метод findTLD. Если все сделано правильно, он должен делать то, что вы хотите, и в этом случае дал бы blogspot.com. - person James P.; 28.08.2011
comment
к @James Poulson, верно. Предположим, я получил tld, псевдо-пример удалит .com из url. Затем он перемещается в позицию точки перед blogspot. Таким образом можно удалить zoyanailpolish . - person chnet; 28.08.2011
comment
Это идея :) . Если у вас возникнут проблемы с его работой, дайте мне знать. - person James P.; 28.08.2011
comment
Возможно, это уже не лучшая идея, поскольку в ближайшие годы появятся тысячи новых TLD. - person andreas; 18.07.2014

Используя библиотеку Guava, мы легко можем получить доменное имя:

InternetDomainName.from(tld).topPrivateDomain()

Обратитесь по ссылке API для получения более подробной информации

https://google.github.io/guava/releases/14.0/api/docs/

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/net/InternetDomainName.html

person Satya    schedule 14.01.2014

Получить хост через REGEX довольно сложно или невозможно, потому что TLD не подчиняются простым правилам, а предоставляются ICANN и меняются со временем.

Вместо этого вы должны использовать функции, предоставляемые библиотекой JAVA, например:

URL myUrl = new URL(urlString);
myUrl.getHost();
person user823959    schedule 27.08.2011
comment
Ну да, но все это у него уже есть. Иногда он хочет сдвинуть некоторое количество ведущих элементов в имени хоста с прямым порядком байтов, хотя он не сказал нам, как узнать, сколько их может быть. Похоже, он думает, что мы можем взглянуть на доменные имена и узнать, является ли та часть, которая у нас есть, уже «основной» или нет. Я не думаю, что это возможно. - person tchrist; 28.08.2011
comment
Для протокола, это не отвечает на вопрос. Это возвращает любое доменное имя, включая субдомен. OP искал имя корневого домена без поддоменов, поэтому, если указан www.google.com, он должен вернуть google.com. Этот метод возвращает www.google.com. Это прекрасно работает, если вы просто пытаетесь получить домен из URL-адреса с путем и / или строкой запроса. - person nerdherd; 08.09.2014

Это 2013 год, и решение, которое я нашел, простое:

System.out.println(InternetDomainName.fromLenient(uriHost).topPrivateDomain().name());
person akshayb    schedule 09.11.2013

Это намного проще:

  try {
        String domainName = new URL("http://www.zoyanailpolish.blogspot.com/some/long/link").getHost();

        String[] levels = domainName.split("\\.");
        if (levels.length > 1)
        {
            domainName = levels[levels.length - 2] + "." + levels[levels.length - 1];
        }

        // now value of domainName variable is blogspot.com
    } catch (Exception e) {}
person Ayaz Alifov    schedule 25.12.2015
comment
Что происходит с: www.zoyanailpolish.blogspot.co.uk - person Clive Paterson; 19.01.2017

Причина, по которой вы видите zoyanailpolish.blogspot.com, заключается в том, что ваше регулярное выражение находит только строки, начинающиеся с 'ww'. Вы спрашиваете, что помимо удаления всех строк, начинающихся с 'ww', это также должно работать для строки, начинающейся с 'zoyanailpolish' (?). В этом случае используйте регулярное выражение String regex = "^((ww|z|a)[a-zA-Z0-9-]{0,}\\.)";. Это удалит все слова, начинающиеся с «ww», «z» или «a». Настройте его в зависимости от того, что именно вам нужно.

person Bhaskar    schedule 27.08.2011
comment
Правильно. в дополнение к удалению всех строк, начинающихся с 'ww'. Это также должно работать для строки, смотрящей на других (не только «zoyanailpolish»). Например, xyz.blogspot.com. - person chnet; 28.08.2011
comment
но, как вы показали для xtop10.net, он не удаляет xtop10 - это означает, что для определенных строк он не удаляет - верно? Вопрос в том, является ли это настраиваемым списком строк, которые вы не хотите удалять, или существует правило, на основе которого это работает? - person Bhaskar; 28.08.2011
comment
to @Bhaskar, это зависит от обстоятельств. Например, xtop10.net, это веб-сайт. Это доменное имя. Мне не нужно вносить никаких изменений. В то время как для zoyanailpolish.blogspot.com имя домена должно быть blogspot.com. Итак, мне нужно удалить zoyanailpolish. - person chnet; 28.08.2011
comment
Совершенно ясно, чего хочет @chnet: Верно. Я хочу основной домен, а не поддомены - person James P.; 28.08.2011
comment
@ Джеймс Это? Тогда он должен был сказать это, не так ли? Надеюсь, ему понравится рассказывать, что .com, .co.uk и pvt.k12.wy.us все считаются одним и тем же. - person tchrist; 28.08.2011
comment
@chnet: Честно говоря, если получение доменного имени вас беспокоит, то использование регулярного выражения - неправильный подход, ИМО. В Java есть и другие методы анализа URL-адресов и извлечения доменных имен. - person Bhaskar; 28.08.2011
comment
@tchrist: Девятый комментарий под вопросом. Я догадался, что нужно, по последней строке URL. Скорее всего, для Regex потребуется ужасное выражение для учета всех возможностей, поэтому были опубликованы альтернативные решения. - person James P.; 28.08.2011

InternetDomainName.from("test.blogspot.com").topPrivateDomain() -> test.blogspot.com

В моем случае это работает лучше:

InternetDomainName.from("test.blogspot.com").topDomainUnderRegistrySuffix() -> blogspot.com

Подробности: https://github.com/google/guava/wiki/InternetDomainNameExplained

person Tinus Tate    schedule 17.05.2019