주어진 URL에서 도메인 이름 가져 오기


130

URL이 주어지면 도메인 이름을 추출하고 싶습니다 ( 'www'부분을 포함하지 않아야 함). URL은 http / https를 포함 할 수 있습니다. 내가 작성한 Java 코드는 다음과 같습니다. 그것은 잘 작동하는 것처럼 보이지만 더 나은 접근 방법이 있거나 가장자리가있는 경우가 있습니다.

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

입력 : http://google.com/blah

출력 : google.com


3
시도 http://74.125.226.70하고 그것이 어떻게 작동하는지 알려주세요 :)
Marvin Pinto

1
IP 주소 만 반환합니다. 74.125.226.70
RandomQuestion

2
도메인 이름 을 어떻게 얻 습니까? 그것이 당신이 추구하는 것이라고 가정 ..
Marvin Pinto

5
예를 들어 http://www.de/또는 http://www.com/원하는 결과를 제공하지 않습니다.
Michael Konietzka

답변:


287

URL을 구문 분석하려면을 사용하십시오 java.net.URI. java.net.URLequals방법은 DNS 조회를 수행하므로 신뢰할 수없는 입력과 함께 사용하는 경우 서비스 거부 공격에 취약 할 수 있습니다.

"고슬링 씨-왜 URL을 빨랐습니까?" 그러한 문제 중 하나를 설명합니다. 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;
}

당신이 원하는 것을해야합니다.


그것은 잘 작동하는 것처럼 보이지만 더 나은 접근 방법이 있거나 가장자리가있는 경우가 있습니다.

유효한 URL에 대해 작성된 코드가 실패합니다.

  • httpfoo/bar-로 시작하는 경로 구성 요소가있는 상대 URL http.
  • HTTP://example.com/ -프로토콜은 대소 문자를 구분하지 않습니다.
  • //example.com/ -호스트가있는 프로토콜 상대 URL
  • www/foo -로 시작하는 경로 구성 요소가있는 상대 URL www
  • wwwexample.com-하지 않는 도메인 이름으로 시작 www.은 있지만 시작됩니다 www.

계층 적 URL에는 복잡한 문법이 있습니다. RFC 3986을주의 깊게 읽지 않고 자신의 파서를 롤링하려고하면 잘못 될 수 있습니다. 핵심 라이브러리에 내장 된 것을 사용하십시오.

java.net.URI거부 되는 지저분한 입력을 처리해야하는 경우 RFC 3986 부록 B를 참조하십시오 .

부록 B. 정규 표현식으로 URI 참조 구문 분석

"first-match-wins"알고리즘은 POSIX 정규식에서 사용하는 "욕심쟁이"명확화 방법과 동일하므로 URI 참조의 잠재적 5 가지 구성 요소를 구문 분석하기 위해 정규식을 사용하는 것이 자연스럽고 일반적입니다.

다음 줄은 올바르게 구성된 URI 참조를 구성 요소로 분류하기위한 정규식입니다.

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

위의 두 번째 줄에있는 숫자는 가독성을 돕기위한 것입니다. 그것들은 각 부분 표현에 대한 기준점을 나타낸다 (즉, 각 쌍 괄호).


2
@Jitendra, 나는 당신이 그것들을 고치기 위해 노력하지 않는 것이 좋습니다. Java 라이브러리 사람들이 이미 작업을 수행했습니다.
Mike Samuel

9
또한 URI의 경우 netUrl = new URI ( "www.google.com"); netUrl.getHost ()는 NULL을 반환합니다. 나는 여전히 http : // 또는 https : //를 확인해야한다고 생각합니다.
RandomQuestion

2
@Jitendra www.google.com는 경로 구성 요소가있는 상대 URL입니다 www.google.com. 예를 들어에 대해 해결 http://example.com/하면을 얻을 수 http://example.com/www.google.com있습니다.
Mike Samuel

고마워 마이크. 라이브러리를 올바르게 이해했다면 위의 URI 또는 ​​정규식을 사용합니까?
RandomQuestion

2
특수 문자를 포함하는 경우 URI 호스트는 null입니다 (예 : "ö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
  }
}

더 읽어보기


15

InternetDomainName.topPrivateDomain()구아바에서 사용하는 짧고 간단한 라인은 다음과 같습니다 .InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

주어진다면 http://www.google.com/blah그것은 당신에게 줄 것 google.com입니다. 또는, http://www.google.co.mx그것은 당신에게 줄 것 google.co.mx입니다.

사 Qada가 에 댓글 이 게시물에 대한 다른 답변 이 질문은 이전 요청되었습니다 주어진 URL에서 주요 도메인 이름의 압축을 풉니 다 . 이 질문에 대한 가장 좋은 답변Satya의 답변입니다. Satya 는 Guava의 InternetDomainName.topPrivateDomain () 을 제안합니다.

공개 부울 isTopPrivateDomain ()

이 도메인 이름이 정확히 하나의 하위 도메인 구성 요소와 공용 접미사로 구성되는지 여부를 나타냅니다. 예를 들어 google.com 및 foo.co.uk의 경우 true를 반환하지만 www.google.com 또는 co.uk의 경우 true를 반환합니다.

경고 :이 방법의 진정한 결과는 많은 공용 접미어도 주소 지정 가능한 호스트이므로 도메인이 호스트로 지정 가능한 최상위 수준임을 의미하지는 않습니다. 예를 들어, bar.uk.com 도메인은 uk.com의 공개 접미어를 가지므로이 메소드에서 true를 리턴합니다. 그러나 uk.com 자체는 주소 지정이 가능한 호스트입니다.

이 방법은 도메인이 쿠키를 설정할 수있는 최상위 레벨인지 여부를 판별하는 데 사용할 수 있지만 개별 브라우저의 쿠키 제어 구현에 따라 달라집니다. 자세한 내용은 RFC 2109를 참조하십시오.

URL.getHost()원래 게시물에 이미 포함되어있는 을 함께 사용하면 다음을 얻을 수 있습니다.

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

URL의 도메인 이름을 추출하고 간단한 문자열 일치를 사용하는 메소드 (아래 참조)를 작성했습니다. 무엇 실제로하는 일은 최초의 비트 추출입니다 "://"(또는 인덱스 0없음있을 경우 "://"포함)과 제 이후 "/"(또는 인덱스를 String.length()후속 존재하지 않는 경우 "/"). 나머지 선행 "www(_)*."비트는 잘립니다. 나는 이것으로 충분하지 않은 경우가있을 것이라고 확신하지만 대부분의 경우 충분해야합니다!

위의 Mike Samuel의 게시물에 따르면 java.net.URI수업 에서이 작업을 수행 할 수 있었으며 수업에 선호 java.net.URL되었지만 수업에 문제가 발생했습니다 URI. 특히, URI.getHost()URL에 스키마, 즉 "http(s)"비트가 포함되지 않은 경우 null 값을 제공합니다 .

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

나는 이것이 맞지 않을 것이라고 생각한다http://bob.com:8080/service/read?name=robert
Lee Meador

Lee를 지적 해 주셔서 감사합니다. "이것으로 충분하지 않은 경우가있을 것입니다 ..."로 답변을 확인했습니다. 내 대답은 특정 사례에 약간의 수정이 필요합니다.
Adil Hussain

3

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

필자의 경우 하위 도메인이 아닌 기본 도메인 만 필요했습니다 ( "www"또는 하위 도메인이 아님).

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

이 방법을 사용하면 URL " https://rest.webtoapp.io/llSlider?lg=en&t=8 "에 "webtoapp.io"도메인이 있습니다.


1

이것을 시도하십시오 : java.net.URL;
JOptionPane.showMessageDialog (null, getDomainName (새 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;
}

설명 : 정규식에는 4 개의 그룹이 있습니다. 처음 두 개는 일치하지 않는 그룹이고 다음 두 개는 일치하는 그룹입니다.

일치하지 않는 첫 번째 그룹은 "http"또는 "https"또는 ""입니다.

일치하지 않는 두 번째 그룹은 "www"입니다. 또는 ""

두 번째 일치 그룹은 최상위 도메인입니다

첫 번째 일치 그룹은 일치하지 않는 그룹 뒤에 있고 최상위 도메인 앞에있는 것입니다.

일치하는 두 그룹을 연결하면 도메인 / 호스트 이름이 제공됩니다.

추신 : 정규식에 지원되는 도메인을 얼마든지 추가 할 수 있습니다.


0

입력 URL이 사용자 입력 인 경우 이 방법은 가장 적합한 호스트 이름을 제공합니다. 찾지 못하면 입력 URL을 반환합니다.

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

위의 모든 것이 좋습니다. 이것은 나에게 정말 간단하고 이해하기 쉬운 것 같습니다. 따옴표를 실례합니다. DataCenter라는 클래스 안에 Groovy를 위해 썼습니다.

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
}

다음은 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

모든 경우에 내가하고 일한 방법 중 하나는 구아바 도서관과 정규식을 함께 사용하는 것입니다.

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 ()은 정규식을 사용하는 일반적인 방법 일 수 있습니다.


0

하위 도메인없이 실제 도메인 이름을 얻으려면 다음을 사용합니다.

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

이는 2 단계 도메인 (예 : .co.uk)에서는 작동하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.