Nhận tên miền từ url đã cho


130

Đưa ra một URL, tôi muốn trích xuất tên miền (Không nên bao gồm phần 'www'). Url có thể chứa http / https. Đây là mã java mà tôi đã viết. Mặc dù nó có vẻ hoạt động tốt, nhưng có cách tiếp cận nào tốt hơn hoặc có một số trường hợp cạnh, điều đó có thể thất bại.

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

Đầu vào: http://google.com/blah

Đầu ra: google.com


3
Hãy thử http://74.125.226.70và cho tôi biết làm thế nào nó hoạt động :)
Marvin Pinto

1
Nó chỉ trả về địa chỉ IP. 74.125.226,70
Câu hỏi ngẫu nhiên

2
Và làm thế nào bạn có được tên miền từ đó? Giả sử đó là những gì bạn đang theo đuổi ..
Marvin Pinto

5
Ví dụ http://www.de/hoặc http://www.com/sẽ không cho kết quả mong muốn.
Michael Konietzka

Câu trả lời:


287

Nếu bạn muốn phân tích một URL, sử dụng java.net.URI. java.net.URLcó một loạt các vấn đề - equalsphương pháp của nó thực hiện tra cứu DNS, có nghĩa là mã sử dụng nó có thể dễ bị từ chối các cuộc tấn công dịch vụ khi được sử dụng với các đầu vào không tin cậy.

"Ông Gosling - tại sao bạn làm cho url bằng hút?" giải thích một vấn đề như vậy Chỉ cần có thói quen sử dụng java.net.URIthay thế.

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

nên làm những gì bạn muốn


Mặc dù nó có vẻ hoạt động tốt, nhưng có cách tiếp cận nào tốt hơn hoặc có một số trường hợp cạnh, điều đó có thể thất bại.

Mã của bạn dưới dạng văn bản không thành công cho các URL hợp lệ:

  • httpfoo/bar- URL tương đối với một thành phần đường dẫn bắt đầu bằng http.
  • HTTP://example.com/ - giao thức không phân biệt chữ hoa chữ thường.
  • //example.com/ - giao thức URL tương đối với một máy chủ
  • www/foo - một URL tương đối có thành phần đường dẫn bắt đầu bằng www
  • wwwexample.com- tên miền không bắt đầu bằng www.nhưng bắt đầu bằng www.

URL phân cấp có ngữ pháp phức tạp. Nếu bạn cố gắng cuộn trình phân tích cú pháp của riêng mình mà không đọc kỹ RFC 3986, có thể bạn sẽ hiểu sai. Chỉ cần sử dụng cái được tích hợp vào thư viện lõi.

Nếu bạn thực sự cần phải xử lý các đầu vào lộn xộn java.net.URItừ chối, hãy xem RFC 3986 Phụ lục B:

Phụ lục B. Phân tích tham chiếu URI bằng biểu thức chính quy

Vì thuật toán "thắng trận đầu tiên" giống hệt với phương pháp định hướng "tham lam" được sử dụng bởi các biểu thức chính quy POSIX, nên việc sử dụng một biểu thức chính quy để phân tích năm thành phần tiềm năng của tham chiếu URI là điều tự nhiên và phổ biến.

Dòng sau đây là biểu thức chính quy để chia nhỏ tham chiếu URI được định dạng tốt thành các thành phần của nó.

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

Các số trong dòng thứ hai ở trên chỉ để hỗ trợ khả năng đọc; chúng chỉ ra các điểm tham chiếu cho mỗi biểu thức con (nghĩa là mỗi dấu ngoặc đơn được ghép nối).


2
@Jitendra, tôi khuyên bạn không nên sửa chúng. Các thư viện Java mọi người đã hoàn thành công việc cho bạn.
Mike Samuel

9
Ngoài ra đối với URI netUrl = URI mới ("www.google.com"); netUrl.gethost () trả về NULL. Tôi nghĩ rằng tôi vẫn cần kiểm tra http: // hoặc https: //
RandomQuestion

2
@Jitendra, www.google.comlà một URL tương đối có thành phần đường dẫn www.google.com. Ví dụ, nếu giải quyết chống lại http://example.com/, bạn sẽ nhận được http://example.com/www.google.com.
Mike Samuel

Cảm ơn Mike ,. Nếu tôi hiểu đúng, với thư viện, ý bạn là, sử dụng URI hoặc regex ở trên?
RandomQuestion

2
Máy chủ URI sẽ là null nếu nó chứa các ký tự đặc biệt, ví dụ: "ö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
  }
}

Đọc thêm


15

Đây là một dòng ngắn và đơn giản sử dụng InternetDomainName.topPrivateDomain()trong ổi:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Cho http://www.google.com/blah, điều đó sẽ cung cấp cho bạn google.com. Hoặc, được đưa ra http://www.google.co.mx, nó sẽ cung cấp cho bạn google.co.mx.

Như Sa Qada đã nhận xét trong một câu trả lời khác trên bài đăng này , câu hỏi này đã được hỏi trước đó: Trích xuất tên miền chính từ một url nhất định . Các câu trả lời tốt nhất cho câu hỏi đó là từ Satya , người gợi ý ổi của InternetDomainName.topPrivateDomain ()

boolean isTopPrivateDomain ()

Cho biết tên miền này có bao gồm chính xác một thành phần tên miền phụ theo sau là hậu tố công khai hay không. Ví dụ: trả về true cho google.com và foo.co.uk, nhưng không phải cho www.google.com hoặc co.uk.

Cảnh báo: Một kết quả thực sự từ phương pháp này không ngụ ý rằng tên miền ở mức cao nhất có thể định địa chỉ là máy chủ lưu trữ, vì nhiều hậu tố công khai cũng là máy chủ lưu trữ địa chỉ. Ví dụ: tên miền bar.uk.com có ​​hậu tố công khai là uk.com, vì vậy nó sẽ trả về true từ phương thức này. Nhưng uk.com là một máy chủ địa chỉ.

Phương pháp này có thể được sử dụng để xác định xem một tên miền có thể là mức cao nhất mà cookie có thể được đặt hay không, mặc dù điều đó phụ thuộc vào việc triển khai kiểm soát cookie của từng trình duyệt riêng lẻ. Xem RFC 2109 để biết chi tiết.

Đặt nó cùng với URL.getHost(), mà bài đăng gốc đã có, mang lại cho bạn:

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

Tôi đã viết một phương thức (xem bên dưới) để trích xuất tên miền của url và sử dụng khớp chuỗi đơn giản. Những gì nó thực sự làm là trích xuất bit giữa đầu tiên "://"(hoặc chỉ mục 0nếu không "://"có) và đầu tiên tiếp theo "/"(hoặc chỉ mục String.length()nếu không có tiếp theo "/"). Phần còn lại, "www(_)*."bit trước được cắt nhỏ. Tôi chắc chắn sẽ có trường hợp điều này sẽ không đủ tốt nhưng nó sẽ đủ tốt trong hầu hết các trường hợp!

Bài đăng của Mike Samuel ở trên nói rằng java.net.URIlớp học có thể làm điều này (và được ưu tiên cho java.net.URLlớp học) nhưng tôi gặp phải vấn đề với URIlớp học. Đáng chú ý, URI.getHost()cung cấp một giá trị null nếu url không bao gồm lược đồ, tức là "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;
}

Tôi nghĩ rằng điều này có thể không đúng chohttp://bob.com:8080/service/read?name=robert
Lee Meador

Cảm ơn đã chỉ ra Lee. Lưu ý rằng tôi đã đủ điều kiện trả lời câu trả lời của mình với "Tôi chắc chắn sẽ có trường hợp điều này sẽ không đủ tốt ...". Câu trả lời của tôi sẽ cần một số sửa đổi nhỏ cho trường hợp cụ thể của bạn.
Adil Hussain

3

Tôi đã thực hiện một điều trị nhỏ sau khi tạo đối tượng 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

Trong trường hợp của tôi, tôi chỉ cần tên miền chính chứ không phải tên miền phụ (không có "www" hoặc bất cứ tên miền phụ nào):

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

Với phương pháp này, url " https://rest.webtoapp.io/llSlider?lg=en&t=8 " sẽ có cho tên miền "webtoapp.io".


1

hãy thử cái này: java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (URL mới (" https://en.wikipedia.org/wiki/List_of_INET_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;
}

Giải thích: regex có 4 nhóm. Hai nhóm đầu là nhóm không khớp và hai nhóm tiếp theo là nhóm phù hợp.

Nhóm không phù hợp đầu tiên là "http" hoặc "https" hoặc ""

Nhóm không khớp thứ hai là "www." hoặc là ""

Nhóm phù hợp thứ hai là tên miền cấp cao nhất

Nhóm phù hợp đầu tiên là bất cứ điều gì sau các nhóm không phù hợp và bất cứ điều gì trước tên miền cấp cao nhất

Sự kết hợp của hai nhóm phù hợp sẽ cung cấp cho chúng tôi tên miền / tên máy chủ lưu trữ.

PS: Lưu ý rằng bạn có thể thêm bất kỳ số lượng tên miền được hỗ trợ nào vào regex.


0

Nếu url đầu vào là đầu vào của người dùng. phương pháp này cho tên máy chủ thích hợp nhất. nếu không tìm thấy sẽ trả lại url đầu vào.

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

Tất cả các bên trên là tốt. Điều này có vẻ thực sự đơn giản với tôi và dễ hiểu. Xin lỗi. Tôi đã viết nó cho Groovy trong một lớp gọi là 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
}

Và đây là một số bài kiểm tra 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

Một trong những cách tôi đã làm và làm việc cho tất cả các trường hợp là sử dụng Thư viện Guava và regex kết hợp.

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 () có thể là bất kỳ phương thức phổ biến nào với regex.


0

Để có được tên miền thực, không có tên miền phụ, tôi sử dụng:

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

Lưu ý rằng điều này sẽ không hoạt động với các tên miền cấp hai (như .co.uk).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.