Получить доменное имя из данного url


учитывая URL, я хочу извлечь доменное имя (оно не должно включать часть "www"). Url может содержать http / https. Вот код java, который я написал. Хотя это, кажется, работает нормально, есть ли лучший подход или есть некоторые крайние случаи, которые могут потерпеть неудачу.

public static String getDomainName(String url) throws MalformedURLException{
    if(!url.startsWith("http") && !url.startsWith("https")){
         url = "http://" + url;
    }        
    URL netUrl = new URL(url);
    String host = netUrl.getHost();
    if(host.startsWith("www")){
        host = host.substring("www".length()+1);
    }
    return host;
}

вход:http://google.com/blah

вывод: google.com

9 94

9 ответов:

если вы хотите разобрать URL-адрес, используйте java.net.URI. java.net.URL есть куча проблем -- его equals метод выполняет поиск DNS, что означает, что код, использующий его, может быть уязвим для атак типа "отказ в обслуживании" при использовании с ненадежными входными данными.

"Мистер Гослинг-почему вы сделали url равно сосать?" объясняет одну из таких проблем. Просто возьмите в привычку использовать java.net.URI вместо.

public static String getDomainName(String url) throws URISyntaxException {
    URI uri = new URI(url);
    String domain = uri.getHost();
    return domain.startsWith("www.") ? domain.substring(4) : domain;
}

должны делать то, что вы хотеть.


хотя это, кажется, работает нормально, есть ли лучший подход или есть некоторые крайние случаи, которые могут потерпеть неудачу.

ваш код, как написано терпит неудачу для допустимых url:

  • httpfoo/bar -- относительный URL-адрес с компонентом пути, который начинается с http.
  • HTTP://example.com/ -- протокол регистр.
  • //example.com/ -- относительный URL протокола с хостом
  • www/foo -- a относительный URL-адрес с компонентом пути, который начинается с www
  • wwwexample.com -- доменное имя, которое не начинается с www. но начинается с www.

иерархические URL-адреса имеют сложную грамматику. Если вы попытаетесь свернуть свой собственный парсер, не внимательно читая RFC 3986, вы, вероятно, ошибетесь. Просто используйте тот, который встроен в ядро библиотеки.

Если вам действительно нужно иметь дело с грязными входами, что java.net.URI отвергает, см. RFC 3986 Приложение B:

приложение B. разбор ссылки URI с регулярным выражением

так как алгоритм "первый матч-победа" идентичен алгоритму " жадный" метод устранения неоднозначности, используемый регулярными выражениями POSIX, это естественно и банально использовать регулярное выражение для разбора потенциальные пять компонентов ссылки URI.

следующая строка является регулярным выражением для разбиения один хорошо сформированная ссылка URI на ее компоненты.

  ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
   12            3  4          5       6  7        8 9

цифры во второй строке выше предназначены только для облегчения чтения; они указывают опорные точки для каждого подвыражения (т. е. парная скобка).

import java.net.*;
import java.io.*;

public class ParseURL {
  public static void main(String[] args) throws Exception {

    URL aURL = new URL("http://example.com:80/docs/books/tutorial"
                       + "/index.html?name=networking#DOWNLOADING");

    System.out.println("protocol = " + aURL.getProtocol()); //http
    System.out.println("authority = " + aURL.getAuthority()); //example.com:80
    System.out.println("host = " + aURL.getHost()); //example.com
    System.out.println("port = " + aURL.getPort()); //80
    System.out.println("path = " + aURL.getPath()); //  /docs/books/tutorial/index.html
    System.out.println("query = " + aURL.getQuery()); //name=networking
    System.out.println("filename = " + aURL.getFile()); ///docs/books/tutorial/index.html?name=networking
    System.out.println("ref = " + aURL.getRef()); //DOWNLOADING
  }
}

подробнее

вот короткая и простая строка с помощью InternetDomainName.topPrivateDomain() в гуава: InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

дано http://www.google.com/blah, это даст вам google.com. Или, учитывая http://www.google.co.mx, это даст вам google.co.mx.

как Са Када прокомментировал еще один ответ на этот пост этот вопрос был задан раньше: извлечение основного доменного имени из заданного url. Элемент лучший ответ на этот вопрос с Сатья, который предполагает, гуава по InternetDomainName.topPrivateDomain ()

public boolean isTopPrivateDomain ()

означает ли это доменное имя состоит из Ровно компонент поддомена, за которым следует публичный суффикс. Например, возвращает правда для google.com и foo.co.uk но не для того, чтобы www.google.com или ко.Великобритания.

предупреждение: истинный результат от этого метода не подразумевает, что домен находится на самом высоком уровне, который адресуется как хозяин, как и многие публичные суффиксы также являются адресными хостами. Например, домен bar.uk.com имеет публичный суффикс uk.com, так что он вернет истину из этот метод. Но ... uk.com сам является адресуемым хостом.

этот метод может быть использован для определения того, является ли домен, вероятно, самый высокий уровень, для которого могут быть установлены куки, хотя даже это зависит на реализации отдельных браузеров элементов управления cookie. См. RFC 2109 для подробности.

положить это вместе с URL.getHost(), который исходный пост уже содержит, дает вам:

import com.google.common.net.InternetDomainName;

import java.net.URL;

public class DomainNameMain {

  public static void main(final String... args) throws Exception {
    final String urlString = "http://www.google.com/blah";
    final URL url = new URL(urlString);
    final String host = url.getHost();
    final InternetDomainName name = InternetDomainName.from(host).topPrivateDomain();
    System.out.println(urlString);
    System.out.println(host);
    System.out.println(name);
  }
}

я написал метод (см. ниже), который извлекает доменное имя url и который использует простое сопоставление строк. То, что он на самом деле делает, это извлечь бит между первым "://" (индекс 0 если нет "://" содержится) и первый последующий "/" (индекс String.length() если нет последующих "/"). Остальные, предшествующие "www(_)*." немного обрублено. Я уверен, что будут случаи, когда это будет недостаточно хорошо, но это должно быть достаточно хорошо в большинстве кейсы!

сообщение Майка Сэмюэля выше говорит, что java.net.URI класс мог это сделать (и был предпочтен java.net.URL класс) но я столкнулся с проблемами с URI класса. Примечательно,URI.getHost() дает нулевое значение, если url не включает схему, т. е.

Я сделал небольшую обработку после создания объекта URI

 if (url.startsWith("http:/")) {
        if (!url.contains("http://")) {
            url = url.replaceAll("http:/", "http://");
        }
    } else {
        url = "http://" + url;
    }
    URI uri = new URI(url);
    String domain = uri.getHost();
    return domain.startsWith("www.") ? domain.substring(4) : domain;

попробуйте это: java. net. URL;
JOptionPane.showMessageDialog (null, getDomainName (new URL ( " https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains")));

public String getDomainName(URL url){
String strDomain;
String[] strhost = url.getHost().split(Pattern.quote("."));
String[] strTLD = {"com","org","net","int","edu","gov","mil","arpa"};

if(Arrays.asList(strTLD).indexOf(strhost[strhost.length-1])>=0)
    strDomain = strhost[strhost.length-2]+"."+strhost[strhost.length-1];
else if(strhost.length>2)
    strDomain = strhost[strhost.length-3]+"."+strhost[strhost.length-2]+"."+strhost[strhost.length-1];
else
    strDomain = strhost[strhost.length-2]+"."+strhost[strhost.length-1];
return strDomain;}

есть аналогичный вопрос извлечение основного доменного имени из заданного url. Если вы посмотрите на это ответ , вы увидите, что это очень легко. Вам просто нужно использовать java.net.URL и String подсобная - Split

private static final String hostExtractorRegexString = "(?:https?://)?(?:www\.)?(.+\.)(com|au\.uk|co\.in|be|in|uk|org\.in|org|net|edu|gov|mil)";
private static final Pattern hostExtractorRegexPattern = Pattern.compile(hostExtractorRegexString);

public static String getDomainName(String url){
    if (url == null) return null;
    url = url.trim();
    Matcher m = hostExtractorRegexPattern.matcher(url);
    if(m.find() && m.groupCount() == 2) {
        return m.group(1) + m.group(2);
    }
    else {
        return null;
    }
}

объяснение : Регулярное выражение имеет 4 группы. Первые две группы не совпадают, а следующие две группы совпадают.

первая несоответствующая группа - "http" или "https "или""

вторая несоответствующая группа - " www."или"

вторая группа-это домен верхнего уровня

первая соответствующая группа-это что-либо после несоответствующих групп и что-либо до верхнего уровня домен

объединение двух соответствующих групп даст нам имя домена / хоста.

ЗЫ : обратите внимание, что вы можете добавить любое количество поддерживаемых доменов в регулярное выражение.

если входной url-адрес является пользовательским вводом. этот метод дает наиболее подходящее имя хоста. если не найдено возвращает входной url.

private String getHostName(String urlInput) {
        urlInput = urlInput.toLowerCase();
        String hostName=urlInput;
        if(!urlInput.equals("")){
            if(urlInput.startsWith("http") || urlInput.startsWith("https")){
                try{
                    URL netUrl = new URL(urlInput);
                    String host= netUrl.getHost();
                    if(host.startsWith("www")){
                        hostName = host.substring("www".length()+1);
                    }else{
                        hostName=host;
                    }
                }catch (MalformedURLException e){
                    hostName=urlInput;
                }
            }else if(urlInput.startsWith("www")){
                hostName=urlInput.substring("www".length()+1);
            }
            return  hostName;
        }else{
            return  "";
        }
    }