Obter nome de domínio de um determinado URL


130

Dado um URL, desejo extrair o nome de domínio (ele não deve incluir a parte 'www'). O URL pode conter http / https. Aqui está o código java que eu escrevi. Embora pareça funcionar bem, existe uma abordagem melhor ou há alguns casos extremos que podem falhar.

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

Entrada: http://google.com/blah

Saída: google.com


3
Experimente http://74.125.226.70e deixe-me saber como isso funciona :)
Marvin Pinto

1
Ele apenas retorna o endereço IP. 74.125.226.70
RandomQuestion

2
E como você obteria o nome de domínio com isso? Assumindo que é que você está depois ..
Marvin Pinto

5
Por exemplo, http://www.de/ou http://www.com/não dará os resultados desejados.
Michael Konietzka

Respostas:


287

Se você deseja analisar um URL, use java.net.URI. java.net.URLtem muitos problemas - seu equalsmétodo faz uma pesquisa de DNS, o que significa que o código usado pode ser vulnerável a ataques de negação de serviço quando usado com entradas não confiáveis.

"Sr. Gosling - por que você fez url igual a merda?" explica um desses problemas. Basta adquirir o hábito de usar 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;
}

deve fazer o que quiser.


Embora pareça funcionar bem, existe uma abordagem melhor ou há alguns casos extremos que podem falhar.

Seu código como escrito falha nos URLs válidos:

  • httpfoo/bar- URL relativo com um componente de caminho que começa com http.
  • HTTP://example.com/ - o protocolo não diferencia maiúsculas de minúsculas.
  • //example.com/ - URL relativo do protocolo com um host
  • www/foo - um URL relativo com um componente de caminho que começa com www
  • wwwexample.com- nome de domínio que não começa com, www.mas começa com www.

URLs hierárquicos têm uma gramática complexa. Se você tentar rolar o seu próprio analisador sem ler atentamente o RFC 3986, provavelmente errará. Basta usar o que está incorporado nas bibliotecas principais.

Se você realmente precisa lidar com entradas confusas que java.net.URIrejeitam, consulte o RFC 3986 Apêndice B:

Apêndice B. Analisando uma Referência de URI com uma Expressão Regular

Como o algoritmo "first-match-wins" é idêntico ao método de desambiguação "ganancioso" usado pelas expressões regulares do POSIX, é natural e comum usar uma expressão regular para analisar os cinco componentes potenciais de uma referência de URI.

A linha a seguir é a expressão regular para decompor uma referência de URI bem formada em seus componentes.

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

Os números na segunda linha acima são apenas para ajudar na legibilidade; eles indicam os pontos de referência para cada subexpressão (ou seja, cada parêntese emparelhado).


2
@Jitendra, eu recomendo que você não trabalhe para corrigi-los. As pessoas das bibliotecas Java já fizeram o trabalho para você.
7608 Mike Samuel

9
Também para URI netUrl = new URI ("www.google.com"); netUrl.getHost () retorna NULL. Acho que ainda preciso procurar por http: // ou https: //
RandomQuestion 7/12/12

2
@Jitendra, www.google.comé uma URL relativa com um componente de caminho que é www.google.com. Por exemplo, se resolvido contra http://example.com/, você obteria http://example.com/www.google.com.
9788 Mike-Samuel Samuel

Obrigado Mike. Se entendi correto, com biblioteca, você quer dizer, use URI ou regex acima?
RandomQuestion

2
Hospedeiro URI será nulo se ele contém caracteres especiais, por exemplo: "ö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
  }
}

Consulte Mais informação


15

Aqui está uma linha curta e simples usando InternetDomainName.topPrivateDomain()na Guava:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Dado http://www.google.com/blah, isso lhe dará google.com. Ou, dado http://www.google.co.mx, isso lhe dará google.co.mx.

Como Sa Qada comentou em outra resposta deste post , essa pergunta foi feita anteriormente: Extraia o nome de domínio principal de um determinado URL . A melhor resposta para essa pergunta é de Satya , que sugere o InternetDomainName.topPrivateDomain () da Guava .

booleano público isTopPrivateDomain ()

Indica se esse nome de domínio é composto de exatamente um componente de subdomínio seguido por um sufixo público. Por exemplo, retorna true para google.com e foo.co.uk, mas não para www.google.com ou co.uk.

Aviso: Um resultado verdadeiro desse método não implica que o domínio esteja no nível mais alto endereçável como host, pois muitos sufixos públicos também são hosts endereçáveis. Por exemplo, o domínio bar.uk.com tem um sufixo público de uk.com; portanto, ele retornará verdadeiro com esse método. Mas o uk.com é um host endereçável.

Esse método pode ser usado para determinar se um domínio é provavelmente o nível mais alto para o qual os cookies podem ser definidos, embora isso dependa das implementações de controles de cookies por navegadores individuais. Veja RFC 2109 para detalhes.

Colocar isso junto com o URL.getHost()que a postagem original já contém fornece:

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

Eu escrevi um método (veja abaixo) que extrai o nome de domínio de um URL e que usa correspondência simples de String. O que ele realmente faz é extrair o bit entre o primeiro "://"(ou índice, 0se não houver "://") e o primeiro subsequente "/"(ou o índice, String.length()se não houver "/"). O restante, o "www(_)*."bit anterior é cortado. Tenho certeza de que haverá casos em que isso não será bom o suficiente, mas na maioria dos casos deve ser bom o suficiente!

O post de Mike Samuel acima diz que a java.net.URIclasse poderia fazer isso (e era preferível à java.net.URLclasse), mas eu encontrei problemas com a URIclasse. Notavelmente, URI.getHost()fornece um valor nulo se o URL não incluir o esquema, ou seja, o "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;
}

Eu acho que isso pode não estar correto parahttp://bob.com:8080/service/read?name=robert
Lee Meador 21/03

Obrigado por apontar Lee. Observe que qualifiquei minha resposta com "Tenho certeza de que haverá casos em que isso não será bom o suficiente ...". Minha resposta precisará de algumas pequenas modificações para o seu caso em particular.
Adil Hussain

3

Fiz um pequeno tratamento após a criação do objeto 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

No meu caso, eu só precisava do domínio principal e não do subdomínio (não "www" ou qualquer que seja o subdomínio):

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

Com este método a url " https://rest.webtoapp.io/llSlider?lg=en&t=8 " terá de domínio "webtoapp.io".


1

tente este: java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (novo 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;
}

Explicação: O regex possui 4 grupos. Os dois primeiros são grupos não correspondentes e os próximos dois são grupos correspondentes.

O primeiro grupo não correspondente é "http" ou "https" ou ""

O segundo grupo não correspondente é "www". ou ""

O segundo grupo correspondente é o domínio de nível superior

O primeiro grupo correspondente é qualquer coisa depois dos grupos não correspondentes e qualquer coisa antes do domínio de nível superior

A concatenação dos dois grupos correspondentes nos fornecerá o nome de domínio / host.

PS: Observe que você pode adicionar qualquer número de domínios suportados à regex.


0

Se o URL de entrada for de entrada do usuário. esse método fornece o nome do host mais apropriado. se não encontrado, retorna o URL de entrada.

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

Todos os itens acima são bons. Este parece realmente simples para mim e fácil de entender. Desculpe as aspas. Eu escrevi para o Groovy dentro de uma classe chamada 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
}

E aqui estão alguns testes do 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

Uma das maneiras que fiz e trabalhei para todos os casos é usar a Biblioteca Guava e o regex em combinação.

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 () pode ser qualquer método comum com regex.


0

Para obter o nome de domínio real, sem o subdomínio, eu uso:

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

Observe que isso não funcionará com domínios de segundo nível (como .co.uk).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.