Holen Sie sich den Domainnamen von der angegebenen URL

130

Bei gegebener URL möchte ich den Domainnamen extrahieren (er sollte keinen 'www'-Teil enthalten). URL kann http / https enthalten. Hier ist der Java-Code, den ich geschrieben habe. Obwohl es gut zu funktionieren scheint, gibt es einen besseren Ansatz oder gibt es einige Randfälle, die fehlschlagen könnten.

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

Eingabe: http://google.com/blah

Ausgabe: google.com

Zufällige Frage
quelle
3
Versuchen Sie http://74.125.226.70und lassen Sie mich wissen, wie das funktioniert :)
Marvin Pinto
1
Es wird nur die IP-Adresse zurückgegeben. 74.125.226.70
RandomQuestion
2
Und wie würden Sie den Domainnamen daraus erhalten? Angenommen, das ist es, wonach Sie suchen.
Marvin Pinto
5
Zum Beispiel http://www.de/oder http://www.com/wird nicht die gewünschten Ergebnisse liefern.
Michael Konietzka

Antworten:

287

Wenn Sie eine URL analysieren möchten, verwenden Sie java.net.URI. java.net.URLhat eine Reihe von Problemen - seine equalsMethode führt eine DNS-Suche durch, was bedeutet, dass der verwendete Code bei Verwendung mit nicht vertrauenswürdigen Eingaben anfällig für Denial-of-Service-Angriffe sein kann.

"Mr. Gosling - warum haben Sie dafür gesorgt, dass URL gleich saugt?" erklärt ein solches Problem. Gewöhnen Sie sich einfach an, java.net.URIstattdessen zu verwenden.

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

sollte tun was du willst.


Obwohl es gut zu funktionieren scheint, gibt es einen besseren Ansatz oder gibt es einige Randfälle, die fehlschlagen könnten.

Ihr geschriebener Code schlägt für die gültigen URLs fehl:

  • httpfoo/bar- relative URL mit einer Pfadkomponente, die mit beginnt http.
  • HTTP://example.com/ - Das Protokoll unterscheidet nicht zwischen Groß- und Kleinschreibung.
  • //example.com/ - Protokoll relative URL mit einem Host
  • www/foo - eine relative URL mit einer Pfadkomponente, die mit beginnt www
  • wwwexample.com- Domainname, der nicht mit, www.sondern mit beginnt www.

Hierarchische URLs haben eine komplexe Grammatik. Wenn Sie versuchen, Ihren eigenen Parser zu rollen, ohne RFC 3986 sorgfältig zu lesen, werden Sie wahrscheinlich etwas falsch machen. Verwenden Sie einfach die in die Kernbibliotheken integrierte.

Wenn Sie wirklich mit unordentlichen Eingaben umgehen müssen, die java.net.URIzurückweisen, lesen Sie RFC 3986 Anhang B:

Anhang B. Analysieren einer URI-Referenz mit einem regulären Ausdruck

Da der "First-Match-Wins" -Algorithmus mit der von POSIX-regulären Ausdrücken verwendeten "gierigen" Disambiguierungsmethode identisch ist, ist es natürlich und üblich, einen regulären Ausdruck zum Parsen der potenziellen fünf Komponenten einer URI-Referenz zu verwenden.

Die folgende Zeile ist der reguläre Ausdruck zum Aufteilen einer wohlgeformten URI-Referenz in ihre Komponenten.

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

Die Zahlen in der zweiten Zeile oben dienen nur zur besseren Lesbarkeit. Sie geben die Referenzpunkte für jeden Unterausdruck an (dh jede gepaarte Klammer).

Mike Samuel
quelle
2
@ Jitendra, ich empfehle dir, nicht daran zu arbeiten, sie zu reparieren. Die Mitarbeiter der Java-Bibliotheken haben die Arbeit bereits für Sie erledigt.
Mike Samuel
9
Auch für URI netUrl = neuer URI ("www.google.com"); netUrl.getHost () gibt NULL zurück. Ich denke, ich muss noch nach http: // oder https: //
RandomQuestion
2
@Jitendra www.google.comist eine relative URL mit einer Pfadkomponente www.google.com. Zum Beispiel, wenn gegen gelöst http://example.com/, würden Sie bekommen http://example.com/www.google.com.
Mike Samuel
Danke Mike. Wenn ich richtig verstanden habe, mit Bibliothek, meinst du, entweder URI oder Regex oben verwenden?
RandomQuestion
2
URI-Host ist null, wenn er Sonderzeichen enthält, zum Beispiel: "ö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
  }
}

Weiterlesen

Michael Tarimo
quelle
15

Hier ist eine kurze und einfache Zeile, die InternetDomainName.topPrivateDomain()in Guave verwendet wird:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Gegeben http://www.google.com/blah, das wird dir geben google.com. Oder gegeben http://www.google.co.mx, es wird dir geben google.co.mx.

Wie Sa Qada in einer anderen Antwort zu diesem Beitrag kommentierte , wurde diese Frage bereits früher gestellt: Extrahieren Sie den Hauptdomainnamen aus einer bestimmten URL . Die beste Antwort auf diese Frage kommt von Satya , die Guavas InternetDomainName.topPrivateDomain () vorschlägt.

public boolean isTopPrivateDomain ()

Gibt an, ob dieser Domänenname aus genau einer Unterdomänenkomponente besteht, gefolgt von einem öffentlichen Suffix. Gibt beispielsweise true für google.com und foo.co.uk zurück, nicht jedoch für www.google.com oder co.uk.

Warnung: Ein echtes Ergebnis dieser Methode bedeutet nicht, dass sich die Domäne auf der höchsten Ebene befindet, die als Host adressierbar ist, da viele öffentliche Suffixe auch adressierbare Hosts sind. Beispielsweise hat die Domain bar.uk.com das öffentliche Suffix uk.com, sodass sie von dieser Methode true zurückgibt. Aber uk.com ist selbst ein adressierbarer Host.

Diese Methode kann verwendet werden, um zu bestimmen, ob eine Domain wahrscheinlich die höchste Ebene ist, für die Cookies gesetzt werden können, obwohl dies auch von der Implementierung der Cookie-Steuerelemente durch einzelne Browser abhängt. Siehe RFC 2109 für Details.

Wenn Sie das zusammenstellen URL.getHost(), was der ursprüngliche Beitrag bereits enthält, erhalten Sie:

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);
  }
}
Kirby
quelle
6

Ich habe eine Methode geschrieben (siehe unten), die den Domainnamen einer URL extrahiert und einen einfachen String-Abgleich verwendet. Was es tatsächlich tut, ist das Bit zwischen dem ersten "://"(oder Index, 0wenn es nicht "://"enthalten ist) und dem ersten nachfolgenden zu extrahieren"/" (oder Index, String.length()wenn es keinen nachfolgenden gibt "/") zu . Das verbleibende vorhergehende "www(_)*."Bit wird abgeschnitten. Ich bin mir sicher, dass es Fälle geben wird, in denen dies nicht gut genug ist, aber in den meisten Fällen sollte es gut genug sein!

Mike Samuels Beitrag oben besagt, dass die java.net.URIKlasse dies tun konnte (und der java.net.URLKlasse vorgezogen wurde ), aber ich hatte Probleme mit der URIKlasse. Gibt insbesondere URI.getHost()einen Nullwert an, wenn die URL das Schema, dh das "http(s)"Bit, nicht enthält.

/**
 * 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;
}
Adil Hussain
quelle
Ich denke, das könnte nicht richtig sein fürhttp://bob.com:8080/service/read?name=robert
Lee Meador
Vielen Dank für den Hinweis auf Lee. Beachten Sie, dass ich meine Antwort mit "Ich bin sicher, dass es Fälle geben wird, in denen dies nicht gut genug ist ..." qualifiziert hat. Meine Antwort muss für Ihren speziellen Fall geringfügig geändert werden.
Adil Hussain
3

Ich habe nach der URI-Objekterstellung eine kleine Behandlung durchgeführt

 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;
Migueloop
quelle
2

In meinem Fall brauchte ich nur die Hauptdomain und nicht die Subdomain (kein "www" oder was auch immer die Subdomain ist):

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

Bei dieser Methode hat die URL " https://rest.webtoapp.io/llSlider?lg=de&t=8 " für die Domain "webtoapp.io".

Laurent
quelle
1

Versuchen Sie dies: java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (neue 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;}
Eko Didik
quelle
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;
}

Erläuterung: Der reguläre Ausdruck besteht aus 4 Gruppen. Die ersten beiden sind nicht übereinstimmende Gruppen und die nächsten beiden sind übereinstimmende Gruppen.

Die erste nicht übereinstimmende Gruppe ist "http" oder "https" oder ""

Die zweite nicht übereinstimmende Gruppe ist "www". oder ""

Die zweite übereinstimmende Gruppe ist die Domäne der obersten Ebene

Die erste übereinstimmende Gruppe ist alles nach den nicht übereinstimmenden Gruppen und alles vor der Domäne der obersten Ebene

Die Verkettung der beiden übereinstimmenden Gruppen gibt uns den Domain- / Hostnamen.

PS: Beachten Sie, dass Sie dem regulären Ausdruck eine beliebige Anzahl unterstützter Domänen hinzufügen können.

Cegprakash
quelle
0

Wenn die Eingabe-URL eine Benutzereingabe ist. Diese Methode gibt den am besten geeigneten Hostnamen an. Wenn nicht gefunden, wird die Eingabe-URL zurückgegeben.

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  "";
        }
    }
spaceMonkey
quelle
0

Alle oben genannten sind gut. Dieser scheint mir wirklich einfach und leicht zu verstehen. Entschuldigen Sie die Zitate. Ich habe es für Groovy in einer Klasse namens DataCenter geschrieben.

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
}

Und hier sind einige junit4-Tests:

@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'
}
Lee Meador
quelle
0

Ich habe in allen Fällen unter anderem Guava Library und Regex in Kombination verwendet.

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 () kann eine beliebige gängige Methode mit Regex sein.

Shivam Yadav
quelle
0

Um den tatsächlichen Domainnamen ohne Subdomain zu erhalten, verwende ich:

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

Beachten Sie, dass dies mit Domains der zweiten Ebene (wie .co.uk) nicht funktioniert.

nickhoffmann7
quelle