Какой самый быстрый способ получить имя домена / хоста из URL? - PullRequest
17 голосов
/ 28 января 2011

Мне нужно просмотреть большой список строковых URL-адресов и извлечь из них доменное имя.

Например:

http://www.stackoverflow.com/questions извлечет www.stackoverflow.com

Первоначально я использовал new URL(theUrlString).getHost(), но инициализация объекта URL добавляет много времени процессу и кажется ненужным.

Существует ли более быстрый способ для извлеченияимя хоста, которое будет столь же надежным?

Спасибо

Редактировать: Моя ошибка, да, www.будет включен в пример доменного имени выше.Кроме того, эти URL могут быть http или https

Ответы [ 8 ]

36 голосов
/ 28 января 2011

Если вы хотите обработать https и т. Д., Я предлагаю вам сделать что-то вроде этого:

int slashslash = url.indexOf("//") + 2;
domain = url.substring(slashslash, url.indexOf('/', slashslash));

Обратите внимание, что это включает в себя часть www (как и URL.getHost()), которая фактически является частью имени домена.

Редактировать Запрошено через комментарии

Вот два метода, которые могут быть полезны:

/**
 * Will take a url such as http://www.stackoverflow.com and return www.stackoverflow.com
 * 
 * @param url
 * @return
 */
public static String getHost(String url){
    if(url == null || url.length() == 0)
        return "";

    int doubleslash = url.indexOf("//");
    if(doubleslash == -1)
        doubleslash = 0;
    else
        doubleslash += 2;

    int end = url.indexOf('/', doubleslash);
    end = end >= 0 ? end : url.length();

    int port = url.indexOf(':', doubleslash);
    end = (port > 0 && port < end) ? port : end;

    return url.substring(doubleslash, end);
}


/**  Based on : http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/android/webkit/CookieManager.java#CookieManager.getBaseDomain%28java.lang.String%29
 * Get the base domain for a given host or url. E.g. mail.google.com will return google.com
 * @param host 
 * @return 
 */
public static String getBaseDomain(String url) {
    String host = getHost(url);

    int startIndex = 0;
    int nextIndex = host.indexOf('.');
    int lastIndex = host.lastIndexOf('.');
    while (nextIndex < lastIndex) {
        startIndex = nextIndex + 1;
        nextIndex = host.indexOf('.', startIndex);
    }
    if (startIndex > 0) {
        return host.substring(startIndex);
    } else {
        return host;
    }
}
8 голосов
/ 28 января 2011

Вы хотите быть очень осторожным с внедрением «быстрого» способа выбора URL-адресов. Существует много потенциальных изменений в URL, которые могут привести к сбою «быстрого» метода. Например:

  • Часть схемы (протокола) может быть написана любой комбинацией прописных и строчных букв; например "http", "Http" и "HTTP" эквивалентны.

  • Полномочия могут дополнительно включать имя пользователя и / или номер порта, как в "http://you@example.com:8080/index.html".

  • Поскольку DNS нечувствителен к регистру, часть имени узла URL также (эффективно) нечувствительна к регистру.

  • Допустимо (хотя и весьма нерегулярно) кодировать незарезервированные символы% в компонентах схемы или полномочий URL-адреса. Это необходимо учитывать при сопоставлении (или устранении) схемы или при интерпретации имени хоста. Имя хоста с символами, кодированными в%, определяется как эквивалентное имени с декодированными последовательностями, кодированными в%.

Теперь, если у вас есть полный контроль над процессом, который генерирует URL-адреса, которые вы удаляете, вы, вероятно, можете игнорировать эти тонкости. Но если они собраны из документов или веб-страниц или введены людьми, вам следует подумать, что может произойти, если ваш код встретит «необычный» URL.


Если вас беспокоит время, затраченное на создание объектов URL, рассмотрите возможность использования объектов URI. Помимо прочего, объекты URI не пытаются выполнить DNS-поиск части имени хоста.

2 голосов
/ 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;
}
1 голос
/ 17 марта 2019

Есть только другой способ получить хост

private String getHostName(String hostname) {
    // to provide faultproof result, check if not null then return only hostname, without www.
    if (hostname != null) {
        return hostname.startsWith("www.") ? hostname.substring(4) : getHostNameDFExt(hostname);
    }
    return hostname;
}

private String getHostNameDFExt(String hostname) {

    int substringIndex = 0;
    for (char character : hostname.toCharArray()) {
        substringIndex++;
        if (character == '.') {
            break;
        }
    }

    return hostname.substring(substringIndex);

}

Теперь мы должны передать имя хоста в функции после извлечения из URL

URL url = new URL("https://www.facebook.com/");
String hostname = getHostName(ur.getHost());

Toast.makeText(this, hostname, Toast.LENGTH_SHORT).show();

Вывод будет: " facebook.com "

1 голос
/ 10 марта 2018

Попробуйте метод: getDomainFromUrl () в этом классе

package com.visc.mobilesecurity.childrencare.utils;

import android.content.Context;

import com.visc.mobilesecurity.antitheft.backwardcompatibility.FroyoSupport;
import com.visc.mobilesecurity.antitheft.util.AntiTheftUtils;
import com.visc.mobilesecurity.constant.Key;
import com.visc.mobilesecurity.util.Prefs;

import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
 * Created by thongnv12 on 3/9/2018.
 */

public class ChildcareUtils {

    public static final String[] NATION_DOMAIN = {"af", "ax", "al", "dz", "as", "ad", "ao", "ai", "aq", "ag", "ar", "am", "aw", "ac", "au", "at", "az", "bs", "bh", "bd", "bb", "eus",
            "by", "be", "bz", "bj", "bm", "bt", "bo", "bq", "ba", "bw", "bv", "br", "io", "vg", "bn", "bg", "bf", "mm", "bi", "kh", "cm", "ca", "cv", "cat", "ky", "cf", "td", "cl",
            "cn", "cx", "cc", "co", "km", "cd", "cg", "ck", "cr", "ci", "hr", "cu", "cw", "cy", "cz", "dk", "dj", "dm", "do", "tl", "ec", "eg", "sv", "gq", "er", "ee", "et", "eu",
            "fk", "fo", "fm", "fj", "fi", "fr", "gf", "pf", "tf", "ga", "gal", "gm", "ps", "ge", "de", "gh", "gi", "gr", "gl", "gd", "gp", "gu", "gt", "gg", "gn", "gw", "gy", "ht",
            "hm", "hn", "hk", "hu", "is", "in", "id", "ir", "iq", "ie", "im", "il", "it", "jm", "jp", "je", "jo", "kz", "ke", "ki", "kw", "kg", "la", "lv", "lb", "ls", "lr", "ly",
            "li", "lt", "lu", "mo", "mk", "mg", "mw", "my", "mv", "ml", "mt", "mh", "mq", "mr", "mu", "yt", "mx", "md", "mc", "mn", "me", "ms", "ma", "mz", "mm", "na", "nr", "np",
            "nl", "nc", "nz", "ni", "ne", "ng", "nu", "nf", "kp", "mp", "no", "om", "pk", "pw", "ps", "pa", "pg", "py", "pe", "ph", "pn", "pl", "pt", "pr", "qa", "ro", "ru", "rw",
            "re", "bq", "bl", "sh", "kn", "lc", "mf", "fr", "pm", "vc", "ws", "sm", "st", "sa", "sn", "rs", "sc", "sl", "sg", "bq", "sx", "sk", "si", "sb", "so", "so", "za", "gs",
            "kr", "ss", "es", "lk", "sd", "sr", "sj", "sz", "se", "ch", "sy", "tw", "tj", "tz", "th", "tg", "tk", "to", "tt", "tn", "tr", "tm", "tc", "tv", "ug", "ua", "ae", "uk",
            "us", "vi", "uy", "uz", "vu", "va", "ve", "vn", "wf", "eh", "zm", "zw"};


    public static boolean isInNationString(String str) {
        for (int index = 0; index < NATION_DOMAIN.length; index++) {
            if (NATION_DOMAIN[index].equals(str)) {
                return true;
            }
        }
        return false;
    }


    public static String getDomainFromUrl(String urlStr) {
        try {
            String result = null;
//            URL url = new URL(urlStr);
//            result = url.getHost();
//            return result;
//
            // for test
            // check dau cach
            if (urlStr.contains(" ")) {
                return null;
            }
            // replace
            urlStr = urlStr.replace("https://", "");
            urlStr = urlStr.replace("http://", "");
            urlStr = urlStr.replace("www.", "");
            //
            String[] splitStr = urlStr.split("/");

            String domainFull = splitStr[0];

            String[] splitDot = domainFull.split("\\.");

            if (splitDot.length < 2) {
                return null;
            }

            String nationStr = splitDot[splitDot.length - 1];

            if (isInNationString(nationStr)) {
                if (splitDot.length < 4) {
                    result = domainFull;
                } else {
                    StringBuilder strResult = new StringBuilder();
                    int lengthDot = splitDot.length;
                    strResult.append(splitDot[lengthDot - 3]).append(".");
                    strResult.append(splitDot[lengthDot - 2]).append(".");
                    strResult.append(splitDot[lengthDot - 1]);
                    result = strResult.toString();
                }

            } else {
                if (splitDot.length < 3) {
                    result = domainFull;
                } else {
                    StringBuilder strResult = new StringBuilder();
                    int lengthDot = splitDot.length;
                    strResult.append(splitDot[lengthDot - 2]).append(".");
                    strResult.append(splitDot[lengthDot - 1]);
                    result = strResult.toString();
                }
            }
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }

    }
}
0 голосов
/ 28 января 2011

Вы можете попробовать использовать регулярные выражения.

http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html

Вот вопрос об извлечении доменного имени с регулярными выражениями в Java:

Регулярное выражение для извлечения domain.tld

0 голосов
/ 28 января 2011

Предполагая, что они все правильно сформированные URL, но вы не знаете, будут ли они http://, https://, и т. Д.


int start = theUrlString.indexOf('/');
int start = theUrlString.indexOf('/', start+1);
int end = theUrlString.indexOf('/', start+1);
String domain = theUrlString.subString(start, end);

0 голосов
/ 28 января 2011

Вы могли бы написать регулярное выражение? http: // всегда одно и то же, а затем сопоставляйте все, пока не получите первый '/'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...