Verilen url'den alan adı alın


130

Bir URL verildiğinde, alan adını çıkarmak istiyorum ('www' kısmını içermemelidir). URL, http / https içerebilir. İşte yazdığım java kodu. İyi çalışıyor gibi görünse de, daha iyi bir yaklaşım var mı veya başarısız olabilecek bazı uç durumlar var mı?

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

Giriş: http://google.com/blah

Çıktı: google.com


3
Deneyin http://74.125.226.70ve bunun nasıl çalıştığını bana bildirin :)
Marvin Pinto

1
Sadece IP adresini döndürür. 74.125.226.70
Rastgele Soru

2
Ve bundan alan adını nasıl alırsınız ? Peşinde olduğun şeyin bu olduğunu varsayarsak ..
Marvin Pinto

5
Örneğin http://www.de/veya http://www.com/istenilen sonuçları vermeyecektir.
Michael Konietzka

Yanıtlar:


287

Bir URL ayrıştırmak istiyorsanız, kullanın java.net.URI. java.net.URLbir sürü sorunu vardır - equalsyöntemi bir DNS araması yapar, bu da onu kullanan kodun, güvenilmeyen girdilerle kullanıldığında hizmet reddi saldırılarına karşı savunmasız olabileceği anlamına gelir.

"Bay Gosling - neden url eşittir berbat yaptınız?" böyle bir sorunu açıklıyor. Bunun java.net.URIyerine kullanmayı alışkanlık haline getirin .

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

ne istersen yapmalısın.


İyi çalışıyor gibi görünse de, daha iyi bir yaklaşım var mı veya başarısız olabilecek bazı uç durumlar var mı?

Yazılan kodunuz geçerli URL'ler için başarısız:

  • httpfoo/bar- ile başlayan bir yol bileşenine sahip göreli URL http.
  • HTTP://example.com/ - protokol büyük / küçük harf duyarlıdır.
  • //example.com/ - bir ana bilgisayarla protokole göre URL
  • www/foo - ile başlayan bir yol bileşenine sahip göreli bir URL www
  • wwwexample.com- ile www.başlamayan ancak ile başlayan alan adı www.

Hiyerarşik URL'lerin karmaşık bir dilbilgisi vardır. RFC 3986'yı dikkatlice okumadan kendi ayrıştırıcınızı döndürmeye çalışırsanız, muhtemelen yanlış anlayacaksınız. Çekirdek kitaplıklarda yerleşik olanı kullanın.

Reddeten karışık girdilerle gerçekten uğraşmanız gerekiyorsa java.net.URI, bkz. RFC 3986 Ek B:

Ek B. Bir URI Referansını Normal Bir İfadeyle Ayrıştırma

"İlk eşleştirme kazanır" algoritması, POSIX normal ifadeleri tarafından kullanılan "açgözlü" belirsizliği giderme yöntemiyle aynı olduğundan, bir URI referansının potansiyel beş bileşenini ayrıştırmak için normal bir ifade kullanmak doğal ve olağandır.

Aşağıdaki satır, iyi biçimlendirilmiş bir URI referansını bileşenlerine ayırmak için kullanılan normal ifadedir.

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

Yukarıdaki ikinci satırdaki sayılar yalnızca okunabilirliğe yardımcı olmak içindir; her bir alt ifade için referans noktalarını gösterirler (yani, her bir çift parantez).


2
@Jitendra, onları düzeltmek için çalışmamanızı tavsiye ederim. Java kütüphaneleri insanları sizin için zaten yaptı.
Mike Samuel

9
Ayrıca URI için netUrl = new URI ("www.google.com"); netUrl.getHost () NULL döndürür. Sanırım hâlâ http: // veya https: //
RandomQuestion

2
@Jitendra, www.google.combir yol bileşeni olan göreli bir URL'dir www.google.com. Örneğin, aleyhine çözülürse http://example.com/, alırsınız http://example.com/www.google.com.
Mike Samuel

Teşekkürler Mike. Kütüphaneyle doğru anladıysam, yukarıdaki URI veya normal ifadeyi mi kullanmak istiyorsunuz?
RandomQuestion

2
URI ana bilgisayarı, özel karakterler içeriyorsa boş olacaktır, örneğin: "ö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
  }
}

Daha fazla oku


15

InternetDomainName.topPrivateDomain()Guava'da kullanılan kısa ve basit bir satır :InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Verildiğinde http://www.google.com/blah, bu size verecektir google.com. Veya verilirse http://www.google.co.mxsize verecektir google.co.mx.

Sa Qada'nın bu gönderideki başka bir yanıtta yorumladığı gibi , bu soru daha önce sorulmuştu: Verilen bir url'den ana alan adını çıkarın . En iyi cevap bu soruya arasındadır Satya Guava en önerir ) (InternetDomainName.topPrivateDomain

public boolean isTopPrivateDomain ()

Bu alan adının tam olarak bir alt alan bileşeninden ve ardından genel bir sonekten oluşup oluşmadığını gösterir. Örneğin, google.com ve foo.co.uk için true döndürür, ancak www.google.com veya co.uk için döndürmez.

Uyarı: Bu yöntemin gerçek bir sonucu, alan adının bir ana bilgisayar olarak adreslenebilen en yüksek düzeyde olduğu anlamına gelmez, çünkü birçok genel son ek de adreslenebilir ana makinelerdir. Örneğin, bar.uk.com etki alanı, uk.com'un genel bir sonekine sahiptir, bu nedenle bu yöntemden true döndürür. Ancak uk.com'un kendisi adreslenebilir bir ana bilgisayardır.

Bu yöntem, bir alan adının muhtemelen tanımlama bilgilerinin ayarlanabileceği en yüksek düzey olup olmadığını belirlemek için kullanılabilir, ancak bu, tek tek tarayıcıların tanımlama bilgisi kontrolleri uygulamalarına bağlıdır. Ayrıntılar için RFC 2109'a bakın.

URL.getHost()Orijinal gönderinin zaten içerdiği ile bunları bir araya getirmek size:

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

Bir url'nin alan adını çıkaran ve basit String eşleştirmesi kullanan bir yöntem (aşağıya bakın) yazdım. Aslında yaptığı ilk arasındaki bit ayıklamak olduğunu "://"(veya dizin 0yok orada eğer "://"içeriyordu) ve birinci müteakip "/"(veya dizin String.length()hiçbir müteakip varsa "/"). Kalan, önceki "www(_)*."bit kesilir. Eminim bunun yeterince iyi olmayacağı durumlar olacaktır, ancak çoğu durumda yeterince iyi olmalıdır!

Mike Samuel'in yukarıdaki yazısı, java.net.URIsınıfın bunu yapabileceğini (ve java.net.URLsınıfa tercih edildiğini) söylüyor, ancak sınıfla ilgili sorunlarla karşılaştım URI. Özellikle, URI.getHost()url şemayı, yani "http(s)"biti içermiyorsa boş bir değer verir .

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

Bunun için doğru olmayabileceğini düşünüyorumhttp://bob.com:8080/service/read?name=robert
Lee Meador

Lee'yi işaret ettiğiniz için teşekkürler. Cevabımı "Eminim bunun yeterince iyi olmayacağı durumlar olacaktır ..." şeklinde nitelendirdiğime dikkat edin. Cevabımın sizin özel durumunuz için biraz değişiklik yapması gerekecek.
Adil Hussain

3

URI nesnesi oluşturulduktan sonra küçük bir işlem yaptım

 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

Benim durumumda alt alan adına değil, yalnızca ana alana ihtiyacım vardı ("www" veya alt alan adı ne olursa olsun):

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

Bu yöntemle " https://rest.webtoapp.io/llSlider?lg=en&t=8 " url'si "webtoapp.io" etki alanına sahip olacaktır.


1

bunu deneyin: java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (yeni 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;
}

Açıklama: Normal ifadenin 4 grubu vardır. İlk ikisi eşleşmeyen gruplardır ve sonraki ikisi eşleşen gruplardır.

Eşleşmeyen ilk grup "http" veya "https" veya "" dir

Eşleşmeyen ikinci grup "www." veya ""

Eşleşen ikinci grup, üst düzey alandır

İlk eşleşen grup, eşleşmeyen gruplardan sonraki herhangi bir şey ve üst düzey alandan önceki herhangi bir şeydir

Eşleşen iki grubun birleştirilmesi bize etki alanı / ana bilgisayar adını verecektir.

Not: Normal ifadeye istediğiniz sayıda desteklenen etki alanı ekleyebileceğinizi unutmayın.


0

Giriş url'si kullanıcı girdisi ise. bu yöntem en uygun ana bilgisayar adını verir. bulunmazsa giriş url'sini geri verir.

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

Yukarıdakilerin hepsi iyidir. Bu bana çok basit ve anlaşılması kolay görünüyor. Alıntıları mazur görün. Bunu Groovy için DataCenter adlı bir sınıfın içinde yazdım.

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
}

Ve işte bazı junit4 testleri:

@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

Tüm vakalar için yaptığım ve çalıştığım yollardan biri de Guava Kitaplığı ve regex'i birlikte kullanmaktı.

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 (), regex ile yaygın olarak kullanılan herhangi bir yöntem olabilir.


0

Alt alan adı olmadan gerçek alan adını almak için şunu kullanıyorum:

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

Bunun ikinci düzey alan adlarında (.co.uk gibi) çalışmayacağını unutmayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.