Uzyskaj nazwę domeny z podanego adresu URL


130

Biorąc pod uwagę adres URL, chcę wyodrębnić nazwę domeny (nie powinna zawierać części „www”). Adres URL może zawierać http / https. Oto kod java, który napisałem. Chociaż wydaje się, że działa dobrze, czy jest jakieś lepsze podejście lub są jakieś skrajne przypadki, które mogą się nie udać.

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;
}

Wejście: http://google.com/blah

Wyjście: google.com


3
Spróbuj http://74.125.226.70i daj mi znać, jak to działa :)
Marvin Pinto

1
Po prostu zwraca adres IP. 74.125.226.70
RandomQuestion

2
Jak uzyskać z tego nazwę domeny ? Zakładając, że tego szukasz ...
Marvin Pinto

5
Na przykład http://www.de/lub http://www.com/nie przyniesie pożądanych rezultatów.
Michael Konietzka

Odpowiedzi:


287

Jeśli chcesz przeanalizować adres URL, użyj java.net.URI. java.net.URLma wiele problemów - jego equalsmetoda wyszukuje DNS, co oznacza, że ​​wykorzystujący ją kod może być podatny na ataki typu „odmowa usługi”, gdy jest używany z niezaufanymi danymi wejściowymi.

"Panie Gosling - dlaczego sprawiłeś, że adres URL jest do niczego?" wyjaśnia jeden taki problem. Po prostu nabądź zwyczaju używania java.net.URIzamiast tego.

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;
}

powinieneś robić, co chcesz.


Chociaż wydaje się, że działa dobrze, czy jest jakieś lepsze podejście lub są jakieś skrajne przypadki, które mogą się nie udać.

Zapisany kod nie działa w przypadku prawidłowych adresów URL:

  • httpfoo/bar- względny adres URL ze składnikiem ścieżki zaczynającym się od http.
  • HTTP://example.com/ - protokół nie rozróżnia wielkości liter.
  • //example.com/ - adres URL protokołu z hostem
  • www/foo - względny adres URL ze składnikiem ścieżki zaczynającym się od www
  • wwwexample.com- nazwa domeny, która nie zaczyna się od, www.ale zaczyna się od www.

Hierarchiczne adresy URL mają złożoną gramatykę. Jeśli spróbujesz zmienić swój własny parser bez uważnego czytania RFC 3986, prawdopodobnie popełnisz błąd. Po prostu użyj tego, który jest wbudowany w podstawowe biblioteki.

Jeśli naprawdę potrzebujesz radzić sobie z niechlujnymi danymi wejściowymi, które java.net.URIodrzucają, zobacz RFC 3986 Dodatek B:

Dodatek B. Analiza odwołania URI za pomocą wyrażenia regularnego

Ponieważ algorytm „pierwsze dopasowanie wygrywa” jest identyczny z „zachłanną” metodą ujednoznaczniania używaną przez wyrażenia regularne POSIX, naturalne i powszechne jest użycie wyrażenia regularnego do analizy potencjalnych pięciu składników odwołania URI.

Poniższy wiersz zawiera wyrażenie regularne służące do rozbicia poprawnie sformułowanego odwołania URI na jego składniki.

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

Liczby w drugim wierszu powyżej służą jedynie do ułatwienia czytelności; wskazują punkty odniesienia dla każdego wyrażenia podrzędnego (tj. każdego sparowanego nawiasu).


2
@Jitendra, radzę nie pracować nad ich naprawą. Biblioteki Javy wykonały już za Ciebie pracę.
Mike Samuel

9
Również dla URI netUrl = new URI („www.google.com”); netUrl.getHost () zwraca NULL. Myślę, że nadal muszę sprawdzić http: // lub https: //
RandomQuestion

2
@Jitendra www.google.comto względny adres URL ze składnikiem ścieżki, którym jest www.google.com. Na przykład, jeśli zostanie rozwiązany przeciwko http://example.com/, otrzymasz http://example.com/www.google.com.
Mike Samuel

Dzięki Mike ,. Jeśli dobrze zrozumiałem, z biblioteką masz na myśli użycie URI lub wyrażenia regularnego powyżej?
RandomQuestion,

2
Host URI będzie miał wartość NULL, jeśli zawiera znaki specjalne, na przykład: „öob.se”
inc

80
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
  }
}

Czytaj więcej


15

Oto krótka i prosta linia używana InternetDomainName.topPrivateDomain()w guawie:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Biorąc pod uwagę http://www.google.com/blah, że to ci da google.com. Albo, biorąc pod uwagę http://www.google.co.mx, da ci google.co.mx.

Jak skomentował Sa Qada w innej odpowiedzi na ten post , to pytanie zostało zadane wcześniej: Wyodrębnij nazwę domeny głównej z podanego adresu URL . Najlepszą odpowiedzią na to pytanie jest od Satya , który sugeruje guawy za InternetDomainName.topPrivateDomain ()

public boolean isTopPrivateDomain ()

Wskazuje, czy ta nazwa domeny składa się z dokładnie jednego składnika subdomeny, po którym następuje publiczny sufiks. Na przykład zwraca wartość true dla google.com i foo.co.uk, ale nie dla www.google.com ani co.uk.

Ostrzeżenie: Prawdziwy wynik tej metody nie oznacza, że ​​domena jest na najwyższym poziomie, który można adresować jako host, ponieważ wiele publicznych sufiksów jest również adresowalnymi hostami. Na przykład domena bar.uk.com ma publiczny sufiks uk.com, więc ta metoda zwróci wartość true. Ale uk.com sam jest hostem adresowalnym.

Tej metody można użyć do określenia, czy domena jest prawdopodobnie najwyższym poziomem, dla którego można ustawić pliki cookie, chociaż nawet to zależy od implementacji kontroli plików cookie w poszczególnych przeglądarkach. Szczegółowe informacje można znaleźć w dokumencie RFC 2109.

Połączenie tego z tym URL.getHost(), co zawiera już oryginalny post, daje:

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);
  }
}

6

Napisałem metodę (patrz poniżej), która wyodrębnia nazwę domeny adresu URL i używa prostego dopasowania String. W rzeczywistości wyodrębnia bit między pierwszym "://"(lub indeksem, 0jeśli nie ma go "://"zawartego), a pierwszym kolejnym "/"(lub indeksem, String.length()jeśli nie ma kolejnego "/"). Pozostały, poprzedni "www(_)*."bit jest odcinany. Jestem pewien, że będą przypadki, w których to nie będzie wystarczająco dobre, ale w większości przypadków powinno być wystarczająco dobre!

Powyższy post Mike'a Samuela mówi, że java.net.URIklasa mogła to zrobić (i była preferowana niż java.net.URLklasa), ale napotkałem problemy z URIklasą. W szczególności URI.getHost()daje wartość null, jeśli adres URL nie zawiera schematu, tj. "http(s)"Bit.

/**
 * Extracts the domain name from {@code url}
 * by means of String manipulation
 * rather than using the {@link URI} or {@link URL} class.
 *
 * @param url is non-null.
 * @return the domain name within {@code url}.
 */
public String getUrlDomainName(String url) {
  String domainName = new String(url);

  int index = domainName.indexOf("://");

  if (index != -1) {
    // keep everything after the "://"
    domainName = domainName.substring(index + 3);
  }

  index = domainName.indexOf('/');

  if (index != -1) {
    // keep everything before the '/'
    domainName = domainName.substring(0, index);
  }

  // check for and remove a preceding 'www'
  // followed by any sequence of characters (non-greedy)
  // followed by a '.'
  // from the beginning of the string
  domainName = domainName.replaceFirst("^www.*?\\.", "");

  return domainName;
}

Myślę, że to może nie być poprawne w przypadkuhttp://bob.com:8080/service/read?name=robert
Lee Meador

Dzięki za wskazanie Lee. Zauważ, że moja odpowiedź została zakwalifikowana przez „Jestem pewien, że będą przypadki, w których to nie będzie wystarczająco dobre ...”. Moja odpowiedź będzie wymagała niewielkich zmian w Twoim konkretnym przypadku.
Adil Hussain

3

Zrobiłem mały zabieg po utworzeniu obiektu 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;

2

W moim przypadku potrzebowałem tylko domeny głównej, a nie subdomeny (bez „www” lub jakiejkolwiek subdomeny):

public static String getUrlDomain(String url) throws URISyntaxException {
    URI uri = new URI(url);
    String domain = uri.getHost();
    String[] domainArray = domain.split("\\.");
    if (domainArray.length == 1) {
        return domainArray[0];
    }
    return domainArray[domainArray.length - 2] + "." + domainArray[domainArray.length - 1];
}

Dzięki tej metodzie adres URL „ https://rest.webtoapp.io/llSlider?lg=en&t=8 ” będzie miał dla domeny „webtoapp.io”.


1

spróbuj tego: java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (nowy adres 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;}


1
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);
    }
    return null;
}

Objaśnienie: wyrażenie regularne ma 4 grupy. Pierwsze dwie to niepasujące grupy, a kolejne dwie to pasujące grupy.

Pierwsza niepasująca grupa to „http”, „https” lub „”

Druga niepasująca grupa to „www”. lub „”

Druga pasująca grupa to domena najwyższego poziomu

Pierwsza pasująca grupa to cokolwiek po niepasujących grupach i wszystko przed domeną najwyższego poziomu

Połączenie dwóch pasujących grup da nam nazwę domeny / hosta.

PS: Pamiętaj, że do wyrażenia regularnego możesz dodać dowolną liczbę obsługiwanych domen.


0

Jeśli wejściowy adres URL jest wprowadzany przez użytkownika. ta metoda daje najbardziej odpowiednią nazwę hosta. jeśli nie znaleziono, zwraca wejściowy adres 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  "";
        }
    }

0

Wszystkie powyższe są dobre. Ten wydaje mi się naprawdę prosty i łatwy do zrozumienia. Przepraszam za cytaty. Napisałem to dla Groovy w klasie o nazwie DataCenter.

static String extractDomainName(String url) {
    int start = url.indexOf('://')
    if (start < 0) {
        start = 0
    } else {
        start += 3
    }
    int end = url.indexOf('/', start)
    if (end < 0) {
        end = url.length()
    }
    String domainName = url.substring(start, end)

    int port = domainName.indexOf(':')
    if (port >= 0) {
        domainName = domainName.substring(0, port)
    }
    domainName
}

A oto kilka testów junit4:

@Test
void shouldFindDomainName() {
    assert DataCenter.extractDomainName('http://example.com/path/') == 'example.com'
    assert DataCenter.extractDomainName('http://subpart.example.com/path/') == 'subpart.example.com'
    assert DataCenter.extractDomainName('http://example.com') == 'example.com'
    assert DataCenter.extractDomainName('http://example.com:18445/path/') == 'example.com'
    assert DataCenter.extractDomainName('example.com/path/') == 'example.com'
    assert DataCenter.extractDomainName('example.com') == 'example.com'
}

0

Jednym ze sposobów, w jaki zrobiłem i pracowałem dla wszystkich przypadków, jest połączenie biblioteki Guava i wyrażenia regularnego.

public static String getDomainNameWithGuava(String url) throws MalformedURLException, 
  URISyntaxException {
    String host =new URL(url).getHost();
    String domainName="";
    try{
        domainName = InternetDomainName.from(host).topPrivateDomain().toString();
    }catch (IllegalStateException | IllegalArgumentException e){
        domainName= getDomain(url,true);
    }
    return domainName;
}

getDomain () może być dowolną popularną metodą z wyrażeniem regularnym.


0

Aby uzyskać rzeczywistą nazwę domeny, bez subdomeny, używam:

private String getDomainName(String url) throws URISyntaxException {
    String hostName = new URI(url).getHost();
    if (!hostName.contains(".")) {
        return hostName;
    }
    String[] host = hostName.split("\\.");
    return host[host.length - 2];
}

Pamiętaj, że to nie zadziała w przypadku domen drugiego poziomu (takich jak .co.uk).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.