Отримайте доменне ім’я з вказаної 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
Випадкові запитання

2
І як би ви отримали від цього доменне ім’я ? Якщо припустити, що ви це хочете ..
Марвін Пінто

5
Наприклад, http://www.de/або http://www.com/не дасть бажаних результатів.
Михайло Коньєтка

Відповіді:


287

Якщо ви хочете розібрати URL-адресу, використовуйте java.net.URI . java.net.URLє маса проблем - його equalsметод здійснює пошук 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 з регулярним виразом

Оскільки алгоритм "перший-матч-виграш" ідентичний методу "жадібного" роз'яснення, використовуваному регулярними виразами POSIX, природно і звичайно використовувати регулярний вираз для розбору потенційних п'яти компонентів посилання URI.

Наступний рядок - це регулярний вираз для розбиття добре сформованої посилання URI на його компоненти.

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

Номери у другому рядку вище лише сприяють читанню; вони вказують опорні точки для кожної піддепресії (тобто для кожної парної дужки).


2
@Jitendra, рекомендую не працювати над їх виправленням. Люди бібліотек Java вже виконали роботу за вас.
Майк Самуель

9
Також для URI netUrl = новий 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.
Майк Самуель

Дякую Майку,. Якщо я зрозумів правильно, під бібліотекою, ви хочете сказати, або використовувати URI або регулярний вираз?
Випадкові запитання

2
Хост URI буде недійсним, якщо він містить спеціальні символи, наприклад: "öob.se"
вкл.

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()в Guava:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

Враховуючи http://www.google.com/blah, це вам дасть google.com. Або, дано http://www.google.co.mx, це вам дасть google.co.mx.

Як прокоментував Са Када в іншій відповіді на цю посаду , це питання було задано раніше: Витягнути основне доменне ім’я з заданої URL-адреси . Найкращою відповіддю на це питання від Satya , який наводить на думку гуави в InternetDomainName.topPrivateDomain ()

загальнодоступний булевий jeTopPrivateDomain ()

Вказує, чи складається з цього доменного імені саме один компонент субдомену, за яким слід публічний суфікс. Наприклад, повертає true для google.com та foo.co.uk, але не для www.google.com чи co.uk.

Попередження: Справжній результат цього методу не означає, що домен знаходиться на найвищому рівні, який може бути адресовано як хост, оскільки багато публічних суфіксів також є хостами, адресованими адресою. Наприклад, домен bar.uk.com має загальнодоступний суфікс uk.com, тому він повертає справжнє з цього методу. Але uk.com сам по собі є адресованим хостом.

Цей метод може бути використаний для визначення того, чи є домен, мабуть, найвищим рівнем, для якого можуть бути встановлені файли cookie, хоча це навіть залежить від реалізації браузерами елементів керування файлами cookie. Докладніше див. У 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(_)*."шматочок відрізають. Я впевнений, що будуть випадки, коли це буде недостатньо добре, але в більшості випадків воно повинно бути досить добрим!

Пост Майка Самуеля говорить, що java.net.URIклас міг би це зробити (і він був відданий перевазі java.net.URLкласу), але у мене виникли проблеми з URIкласом. Зокрема, URI.getHost()дає нульове значення, якщо URL не включає схему, тобто "http(s)"біт.

/**
 * 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
Лі Медор

Дякуємо, що вказали на Лі. Зауважте, що я відповів, що я відповів "я впевнений, що будуть випадки, коли це буде недостатньо добре ...". Моя відповідь потребує незначної модифікації для вашого конкретного випадку.
Аділ

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". або ""

Друга відповідна група - домен верхнього рівня

Першою групою, що відповідає, є будь-що після невідповідних груп і нічого перед доменом верхнього рівня

З'єднання двох відповідних груп дасть нам ім'я домену / хоста.

PS: Зауважте, що ви можете додати будь-яку кількість підтримуваних доменів до регулярного виразу.


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

Все вищезазначене добре. Це здається мені дуже простим і зрозумілим. Вибачте цитати. Я написав це для Groovy всередині класу під назвою 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
}

Ось кілька тестів 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

Один із способів, які я робив і працював у всіх випадках, - це використання бібліотеки Guava та регулярного виразу.

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

Зауважте, що це не буде працювати з доменами другого рівня (наприклад, .co.uk).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.