Dapatkan nama domain dari url yang diberikan

130

Diberikan URL, saya ingin mengekstrak nama domain (Seharusnya tidak termasuk bagian 'www'). Url dapat berisi http / https. Berikut adalah kode java yang saya tulis. Meskipun tampaknya berfungsi dengan baik, apakah ada pendekatan yang lebih baik atau ada beberapa kasus tepi, yang bisa gagal.

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

Input: http://google.com/blah

Output: google.com

Pertanyaan Acak
sumber
3
Coba http://74.125.226.70dan beri tahu saya cara kerjanya :)
Marvin Pinto
1
Itu hanya mengembalikan alamat IP. 74.125.226.70
RandomQuestion
2
Dan bagaimana Anda mendapatkan nama domain dari itu? Dengan asumsi itulah yang Anda cari ..
Marvin Pinto
5
Misalnya http://www.de/atau http://www.com/tidak akan memberikan hasil yang diinginkan.
Michael Konietzka

Jawaban:

287

Jika Anda ingin menguraikan URL, gunakan java.net.URI. java.net.URLmemiliki banyak masalah - equalsmetodenya melakukan pencarian DNS yang berarti kode yang menggunakannya dapat rentan terhadap serangan penolakan layanan ketika digunakan dengan input yang tidak dipercaya.

"Mr. Gosling - mengapa Anda membuat url sama dengan mengisap?" menjelaskan satu masalah seperti itu. Biasakan menggunakan saja java.net.URIsebagai gantinya.

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

harus melakukan apa yang Anda inginkan.


Meskipun tampaknya berfungsi dengan baik, apakah ada pendekatan yang lebih baik atau ada beberapa kasus tepi, yang bisa gagal.

Kode Anda sebagai tulisan gagal untuk URL yang valid:

  • httpfoo/bar- URL relatif dengan komponen jalur yang dimulai dengan http.
  • HTTP://example.com/ - protokol tidak peka huruf besar-kecil.
  • //example.com/ - protokol URL relatif dengan host
  • www/foo - URL relatif dengan komponen jalur yang dimulai dengan www
  • wwwexample.com- nama domain yang tidak dimulai dengan www.tetapi dimulai dengan www.

URL hierarkis memiliki tata bahasa yang kompleks. Jika Anda mencoba untuk menggulung parser Anda sendiri tanpa membaca RFC 3986 dengan hati-hati, Anda mungkin salah. Cukup gunakan yang dibangun ke perpustakaan inti.

Jika Anda benar-benar harus berurusan dengan input berantakan yang java.net.URImenolak, lihat RFC 3986 Lampiran B:

Lampiran B. Mengurai Referensi URI dengan Ekspresi Reguler

Karena algoritme "pertandingan pertama menang" identik dengan metode disambiguasi "serakah" yang digunakan oleh ekspresi reguler POSIX, wajar dan umum untuk menggunakan ekspresi reguler untuk mengurai lima komponen potensial dari referensi URI.

Baris berikut adalah ekspresi reguler untuk memecah referensi URI yang terbentuk dengan baik ke dalam komponen-komponennya.

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

Angka-angka pada baris kedua di atas hanya untuk membantu keterbacaan; mereka menunjukkan titik referensi untuk setiap sub-ekspresi (yaitu, masing-masing tanda kurung dipasangkan).

Mike Samuel
sumber
2
@Jitendra, saya sarankan Anda tidak berusaha memperbaikinya. Orang-orang perpustakaan Java sudah melakukan pekerjaan untuk Anda.
Mike Samuel
9
Juga untuk URI netUrl = URI baru ("www.google.com"); netUrl.getHost () mengembalikan NULL. Saya rasa saya masih perlu memeriksa http: // atau https: //
RandomQuestion
2
@Jitendra, www.google.comadalah URL relatif dengan komponen jalur itu www.google.com. Misalnya, jika diselesaikan http://example.com/, Anda akan mendapatkannya http://example.com/www.google.com.
Mike Samuel
Terima kasih, Mike. Jika saya mengerti benar, dengan perpustakaan, maksud Anda, apakah menggunakan URI atau regex di atas?
RandomQuestion
2
Tuan rumah URI akan menjadi nol jika berisi karakter khusus, misalnya: "ö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
  }
}

Baca lebih lajut

Michael Tarimo
sumber
15

Berikut ini adalah garis pendek dan sederhana yang digunakan InternetDomainName.topPrivateDomain()di Jambu:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Mengingat http://www.google.com/blah, itu akan memberi Anda google.com. Atau, mengingat http://www.google.co.mx, itu akan memberi Anda google.co.mx.

Seperti Sa Qada berkomentar dalam jawaban lain pada posting ini, pertanyaan ini telah ditanyakan sebelumnya: Ekstrak nama domain utama dari url yang diberikan . The jawaban terbaik untuk pertanyaan itu adalah dari Satya , yang menyarankan Guava ini InternetDomainName.topPrivateDomain ()

public boolean isTopPrivateDomain ()

Menunjukkan apakah nama domain ini terdiri dari tepat satu komponen subdomain yang diikuti oleh akhiran publik. Misalnya, mengembalikan true untuk google.com dan foo.co.uk, tetapi tidak untuk www.google.com atau co.uk.

Peringatan: Hasil sebenarnya dari metode ini tidak menyiratkan bahwa domain berada pada tingkat tertinggi yang dapat dialamatkan sebagai host, karena banyak sufiks publik juga merupakan host yang dapat dialamatkan. Misalnya, domain bar.uk.com memiliki akhiran publik dari uk.com, jadi itu akan mengembalikan true dari metode ini. Tapi uk.com sendiri adalah host yang bisa dialamatkan.

Metode ini dapat digunakan untuk menentukan apakah suatu domain mungkin merupakan level tertinggi untuk cookie yang mungkin ditetapkan, meskipun itu pun tergantung pada implementasi kontrol cookie oleh masing-masing browser. Lihat RFC 2109 untuk detailnya.

Menyatukannya dengan URL.getHost(), yang sudah berisi pos asli, memberi Anda:

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
sumber
6

Saya menulis sebuah metode (lihat di bawah) yang mengekstrak nama domain url dan yang menggunakan pencocokan String sederhana. Apa yang sebenarnya dilakukannya adalah mengekstrak bit antara yang pertama "://"(atau indeks 0jika tidak ada yang "://"terkandung) dan yang berikutnya berikutnya "/"(atau indeks String.length()jika tidak ada yang berikutnya "/"). Yang tersisa, sebelumnya"www(_)*."Bit yang dipotong. Saya yakin akan ada kasus di mana ini tidak akan cukup baik tetapi harus cukup baik dalam banyak kasus!

Posting Mike Samuel di atas mengatakan bahwa java.net.URIkelas dapat melakukan ini (dan lebih disukai daripada java.net.URLkelas) tetapi saya mengalami masalah dengan URIkelas. Khususnya, URI.getHost()memberikan nilai nol jika url tidak termasuk skema, yaitu "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;
}
Adil Hussain
sumber
Saya pikir ini mungkin tidak benar untukhttp://bob.com:8080/service/read?name=robert
Lee Meador
Terima kasih telah menunjukkan Lee. Perhatikan bahwa saya memenuhi syarat jawaban saya dengan "Saya yakin akan ada kasus di mana ini tidak akan cukup baik ...". Jawaban saya perlu sedikit modifikasi untuk kasus khusus Anda.
Adil Hussain
3

Saya melakukan perawatan kecil setelah pembuatan objek 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;
migueloop
sumber
2

Dalam kasus saya, saya hanya perlu domain utama dan bukan subdomain (tidak ada "www" atau apa pun subdomain itu):

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

Dengan metode ini url " https://rest.webtoapp.io/llSlider?lg=en&t=8 " akan memiliki untuk domain "webtoapp.io".

Laurent
sumber
1

coba yang ini: java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (URL baru (" 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
sumber
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;
}

Penjelasan: Regex memiliki 4 grup. Dua yang pertama adalah grup yang tidak cocok dan dua yang berikutnya adalah grup yang cocok.

Grup tidak cocok pertama adalah "http" atau "https" atau ""

Grup tidak cocok kedua adalah "www." atau ""

Grup pencocokan kedua adalah domain tingkat atas

Grup pencocokan pertama adalah apa saja setelah grup yang tidak cocok dan apa pun sebelum domain tingkat atas

Rangkuman dari dua grup yang cocok akan memberi kita nama domain / host.

PS: Perhatikan bahwa Anda dapat menambahkan sejumlah domain yang didukung ke regex.

cegprakash
sumber
0

Jika url input adalah input pengguna. metode ini memberikan nama host yang paling tepat. jika tidak ditemukan berikan kembali url input.

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
sumber
0

Semua hal di atas baik. Yang ini sepertinya sangat sederhana bagi saya dan mudah dimengerti. Maafkan kutipan. Saya menulisnya untuk Groovy di dalam kelas yang disebut 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
}

Dan inilah beberapa tes 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'
}
Lee Meador
sumber
0

Salah satu cara yang saya lakukan dan bekerja untuk semua kasus adalah menggunakan Perpustakaan Guava dan regex dalam kombinasi.

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 () dapat berupa metode umum dengan regex.

Shivam Yadav
sumber
0

Untuk mendapatkan nama domain yang sebenarnya, tanpa subdomain, saya menggunakan:

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

Perhatikan bahwa ini tidak akan berfungsi dengan domain tingkat kedua (seperti .co.uk).

nickhoffmann7
sumber