Получить доменное имя по указанному URL - PullRequest
107 голосов
/ 07 марта 2012

Учитывая URL, я хочу извлечь доменное имя (оно не должно включать часть 'www').URL может содержать http / https.Вот код Java, который я написал.Хотя кажется, что он работает нормально, есть ли лучший подход или есть некоторые крайние случаи, которые могут потерпеть неудачу.*

Ответы [ 11 ]

252 голосов
/ 07 марта 2012

Если вы хотите проанализировать 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

Цифры во второй строке выше предназначены только для удобства чтения; они указывают контрольные точки для каждого подвыражения (т.е. каждый парные скобки).

66 голосов
/ 27 февраля 2014
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
  }
}

Подробнее

10 голосов
/ 21 сентября 2016

Вот короткая и простая строка с использованием 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.

Как Sa Qada прокомментировал в другой ответ на этот пост , этот вопрос был задан ранее: Извлечение основного доменного имени из заданного URL . лучший ответ на этот вопрос от Satya , который предлагает GuDo's InternetDomainName.topPrivateDomain ()

public boolean isTopPrivateDomain ()

Указывает, состоит ли это доменное имя из ровно одного компонент субдомена, за которым следует общедоступный суффикс. Например, возвращает верно для google.com и foo.co.uk, но не для www.google.com или co.uk.

Предупреждение: истинный результат этого метода не означает, что домен находится на самом высоком уровне, который можно адресовать как хост, так много публичные суффиксы также являются адресуемыми хостами. Например, домен bar.uk.com имеет публичный суффикс uk.com, поэтому он будет возвращать true из Этот метод. Но uk.com сам по себе является адресуемым хостом.

Этот метод может использоваться для определения того, является ли домен наивысший уровень, для которого могут быть установлены куки, хотя даже это зависит В отдельных браузерах реализованы элементы управления 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);
  }
}
4 голосов
/ 23 ноября 2013

Я написал метод (см. Ниже), который извлекает доменное имя 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;
}
2 голосов
/ 04 ноября 2014

Я сделал небольшую обработку после создания объекта 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;
1 голос
/ 07 декабря 2018

В моем случае мне нужен был только основной домен, а не поддомен (без "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];
    }
    else {
        return domainArray[domainArray.length - 2] + "." + domainArray[domainArray.length - 1];
    }
}

При использовании этого метода URL "https://rest.webtoapp.io/llSlider?lg=en&t=8" будетесть для домена "webtoapp.io".

1 голос
/ 03 ноября 2016
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);
    }
    else {
        return null;
    }
}

Объяснение: Регулярное выражение имеет 4 группы. Первые две являются несоответствующими группами, а следующие две являются совпадающими группами.

Первой несоответствующей группой является "http" или "https" или ""

Вторая несоответствующая группа - "www." или ""

Вторая подходящая группа - это домен верхнего уровня

Первая подходящая группа - это что-нибудь после несоответствующих групп и что-либо перед доменом верхнего уровня

Объединение двух соответствующих групп даст нам имя домена / хоста.

PS: обратите внимание, что к регулярному выражению можно добавить любое количество поддерживаемых доменов.

1 голос
/ 26 декабря 2015

Есть похожий вопрос Извлечение основного доменного имени из заданного URL .Если вы посмотрите на этот ответ , вы увидите, что это очень просто.Вам просто нужно использовать утилиту java.net.URL и String - Split

1 голос
/ 06 июля 2015

попробуйте это: 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;}
0 голосов
/ 21 марта 2019

Все вышеперечисленное хорошо.Этот кажется мне действительно простым и легким для понимания.Извините цитаты.Я написал его для 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'
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...