Как получить доменное имя из URL-адреса

Как получить имя домена из строки URL?

Примеры:

+----------------------+------------+
| input                | output     |
+----------------------+------------+
| www.google.com       | google     |
| www.mail.yahoo.com   | mail.yahoo |
| www.mail.yahoo.co.in | mail.yahoo |
| www.abc.au.uk        | abc        |
+----------------------+------------+

по теме:

Ответ 1

Мне приходилось писать такое регулярное выражение для компании, в которой я работал. Решением было следующее:

  • Получить список всех ccTLD и gTLD доступно. Ваша первая остановка должна быть IANA. Список из Mozilla выглядит великолепно с первого взгляда, но, к примеру, отсутствует ac.uk, поэтому для этого он не может использоваться.
  • Присоединитесь к списку, как показано ниже. Предупреждение: Заказ важен! Если org.uk появится после uk, тогда example.org.uk будет соответствовать org вместо example.

Пример regex:

.*([^\.]+)(com|net|org|info|coop|int|co\.uk|org\.uk|ac\.uk|uk|__and so on__)$

Это работало очень хорошо, а также соответствовало странным, неофициальным топ-уровням, таким как de.com и друзьям.

Потенциал роста:

  • Очень быстро, если регулярное выражение упорядочено оптимально

Недостатком этого решения является, конечно:

  • Рукописное регулярное выражение, которое необходимо обновить вручную, если ccTLD меняются или добавляются. Занимательная работа!
  • Очень большое регулярное выражение, поэтому оно не очень читаемо.

Ответ 2

/^(?:www\.)?(.*?)\.(?:com|au\.uk|co\.in)$/

Ответ 3

/* These are TLDs that have an SLD */
var tlds = {
    "cy":true,
    "ro":true,
    "ke":true,
    "kh":true,
    "ki":true,
    "cr":true,
    "km":true,
    "kn":true,
    "kr":true,
    "ck":true,
    "cn":true,
    "kw":true,
    "rs":true,
    "ca":true,
    "kz":true,
    "rw":true,
    "ru":true,
    "za":true,
    "zm":true,
    "bz":true,
    "je":true,
    "uy":true,
    "bs":true,
    "br":true,
    "jo":true,
    "us":true,
    "bh":true,
    "bo":true,
    "bn":true,
    "bb":true,
    "ba":true,
    "ua":true,
    "eg":true,
    "ec":true,
    "et":true,
    "er":true,
    "es":true,
    "pl":true,
    "in":true,
    "ph":true,
    "il":true,
    "pe":true,
    "co":true,
    "pa":true,
    "id":true,
    "py":true,
    "ug":true,
    "ky":true,
    "ir":true,
    "pt":true,
    "pw":true,
    "iq":true,
    "it":true,
    "pr":true,
    "sh":true,
    "sl":true,
    "sn":true,
    "sa":true,
    "sb":true,
    "sc":true,
    "sd":true,
    "se":true,
    "hk":true,
    "sg":true,
    "sy":true,
    "sz":true,
    "st":true,
    "sv":true,
    "om":true,
    "th":true,
    "ve":true,
    "tz":true,
    "vn":true,
    "vi":true,
    "pk":true,
    "fk":true,
    "fj":true,
    "fr":true,
    "ni":true,
    "ng":true,
    "nf":true,
    "re":true,
    "na":true,
    "qa":true,
    "tw":true,
    "nr":true,
    "np":true,
    "ac":true,
    "af":true,
    "ae":true,
    "ao":true,
    "al":true,
    "yu":true,
    "ar":true,
    "tj":true,
    "at":true,
    "au":true,
    "ye":true,
    "mv":true,
    "mw":true,
    "mt":true,
    "mu":true,
    "tr":true,
    "mz":true,
    "tt":true,
    "mx":true,
    "my":true,
    "mg":true,
    "me":true,
    "mc":true,
    "ma":true,
    "mn":true,
    "mo":true,
    "ml":true,
    "mk":true,
    "do":true,
    "dz":true,
    "ps":true,
    "lr":true,
    "tn":true,
    "lv":true,
    "ly":true,
    "lb":true,
    "lk":true,
    "gg":true,
    "uk":true,
    "gn":true,
    "gh":true,
    "gt":true,
    "gu":true,
    "jp":true,
    "gr":true,
    "nz":true
}

function isSecondLevelDomainPresent(domainParts) {
    return typeof tlds[domainParts[domainParts.length-1]] != "undefined";
}
function getDomainFromHostname(url) {
  domainParts = url.split(".");
  var cutOff =2;
  if (isSecondLevelDomainPresent(domainParts)) {
    cutOff=3;
  }
  return domainParts.slice(domainParts.length-cutOff, domainParts.length).join(".");
}

Вместо того, чтобы писать большое регулярное выражение, почему бы не взять список известных TLD, которые требуют SLD, и построить из них хеш-таблицу. Затем, когда вы разделите URL-адрес, вы можете узнать, следует ли брать последние 2 части или последние 3.

Ответ 4

Я не знаю каких-либо библиотек, но манипуляции с именами доменов довольно просто.

Жесткая часть - это знать, находится ли имя на втором или третьем уровне. Для этого вам понадобится файл данных, который вы поддерживаете (например, для .uk не всегда является третьим уровнем, некоторые организации (например, bl.uk, jet.uk) существуют на втором уровне).

источник Firefox из Mozilla имеет такой файл данных, проверьте лицензирование Mozilla, чтобы узнать, можете ли вы его повторно использовать.

Ответ 5

import urlparse

GENERIC_TLDS = [
    'aero', 'asia', 'biz', 'com', 'coop', 'edu', 'gov', 'info', 'int', 'jobs', 
    'mil', 'mobi', 'museum', 'name', 'net', 'org', 'pro', 'tel', 'travel', 'cat'
    ]

def get_domain(url):
    hostname = urlparse.urlparse(url.lower()).netloc
    if hostname == '':
        # Force the recognition as a full URL
        hostname = urlparse.urlparse('http://' + uri).netloc

    # Remove the 'user:passw', 'www.' and ':port' parts
    hostname = hostname.split('@')[-1].split(':')[0].lstrip('www.').split('.')

    num_parts = len(hostname)
    if (num_parts < 3) or (len(hostname[-1]) > 2):
        return '.'.join(hostname[:-1])
    if len(hostname[-2]) > 2 and hostname[-2] not in GENERIC_TLDS:
        return '.'.join(hostname[:-1])
    if num_parts >= 3:
        return '.'.join(hostname[:-2])

Этот код не гарантирует работу со всеми URL-адресами и не фильтрует те, которые являются грамматически правильными, но недействительными, например, example.uk.

Однако он будет выполнять эту работу в большинстве случаев.

Ответ 6

Существует два способа:

Использование split

Затем просто проанализируйте эту строку

var domain;
//find & remove protocol (http, ftp, etc.) and get domain
if (url.indexOf('://') > -1) {
    domain = url.split('/')[2];
} if (url.indexOf('//') === 0) {
    domain = url.split('/')[2];
} else {
    domain = url.split('/')[0];
}

//find & remove port number
domain = domain.split(':')[0];

Использование Regex

 var r = /:\/\/(.[^/]+)/;
 "http://stackoverflow.com/questions/5343288/get-url".match(r)[1] 
 => stackoverflow.com

Надеюсь, что это поможет

Ответ 7

Извлечение доменного имени точно может быть довольно сложным, главным образом потому, что расширение домена может содержать 2 части (например,.com.au или .co.uk), а субдомен (префикс) может быть или не быть. Список всех расширений домена не является вариантом, потому что их сотни. Например, в EuroDNS.com перечислены более 800 расширений доменных имен.

Поэтому я написал короткую функцию php, которая использует "parse_url()", и некоторые замечания о расширениях домена для точного извлечения компонентов URL и имени домена. Функция следующая:

function parse_url_all($url){
    $url = substr($url,0,4)=='http'? $url: 'http://'.$url;
    $d = parse_url($url);
    $tmp = explode('.',$d['host']);
    $n = count($tmp);
    if ($n>=2){
        if ($n==4 || ($n==3 && strlen($tmp[($n-2)])<=3)){
            $d['domain'] = $tmp[($n-3)].".".$tmp[($n-2)].".".$tmp[($n-1)];
            $d['domainX'] = $tmp[($n-3)];
        } else {
            $d['domain'] = $tmp[($n-2)].".".$tmp[($n-1)];
            $d['domainX'] = $tmp[($n-2)];
        }
    }
    return $d;
}

Эта простая функция будет работать практически в каждом случае. Есть несколько исключений, но они очень редки.

Чтобы продемонстрировать/протестировать эту функцию, вы можете использовать следующее:

$urls = array('www.test.com', 'test.com', 'cp.test.com' .....);
echo "<div style='overflow-x:auto;'>";
echo "<table>";
echo "<tr><th>URL</th><th>Host</th><th>Domain</th><th>Domain X</th></tr>";
foreach ($urls as $url) {
    $info = parse_url_all($url);
    echo "<tr><td>".$url."</td><td>".$info['host'].
    "</td><td>".$info['domain']."</td><td>".$info['domainX']."</td></tr>";
}
echo "</table></div>";

Для указанного URL-адреса вывод будет следующим:

введите описание изображения здесь

Как вы можете видеть, доменное имя и имя домена без расширения последовательно извлекаются независимо от URL-адреса, который представлен этой функции.

Я надеюсь, что это поможет.

Ответ 8

В принципе, вы хотите:

google.com        -> google.com    -> google
www.google.com    -> google.com    -> google
google.co.uk      -> google.co.uk  -> google
www.google.co.uk  -> google.co.uk  -> google
www.google.org    -> google.org    -> google
www.google.org.uk -> google.org.uk -> google

Дополнительно:

www.google.com     -> google.com    -> www.google
images.google.com  -> google.com    -> images.google
mail.yahoo.co.uk   -> yahoo.co.uk   -> mail.yahoo
mail.yahoo.com     -> yahoo.com     -> mail.yahoo
www.mail.yahoo.com -> yahoo.com     -> mail.yahoo

Вам не нужно создавать постоянно изменяющееся регулярное выражение, так как 99% доменов будут правильно подобраны, если вы просто посмотрите на вторую последнюю часть имени:

(co|com|gov|net|org)

Если это один из них, вам нужно сопоставить 3 точки, иначе 2. Простой. Теперь мое волшебство регулярных выражений не подходит для некоторых других SO'ers, поэтому наилучшим способом, который я нашел для этого, является некоторый код, предполагая, что вы уже отключили путь:

 my @d=split /\./,$domain;                # split the domain part into an array
 [email protected];                                   # count how many parts
 $dest=$d[$c-2].'.'.$d[$c-1];             # use the last 2 parts
 if ($d[$c-2]=~m/(co|com|gov|net|org)/) { # is the second-last part one of these?
   $dest=$d[$c-3].'.'.$dest;              # if so, add a third part
 };
 print $dest;                             # show it

Чтобы просто получить имя, в соответствии с вашим вопросом:

 my @d=split /\./,$domain;                # split the domain part into an array
 [email protected];                                   # count how many parts
 if ($d[$c-2]=~m/(co|com|gov|net|org)/) { # is the second-last part one of these?
   $dest=$d[$c-3];                        # if so, give the third last
   $dest=$d[$c-4].'.'.$dest if ($c>3);    # optional bit
 } else {
   $dest=$d[$c-2];                        # else the second last
   $dest=$d[$c-3].'.'.$dest if ($c>2);    # optional bit 
 };
 print $dest;                             # show it

Мне нравится этот подход, потому что он не требует обслуживания. Если вы не хотите проверять, что это фактически законный домен, но это бессмысленно, потому что вы, скорее всего, используете это только для обработки файлов журнала, а недопустимый домен не нашел бы его там, в первую очередь.

Если вы хотите совместить "неофициальные" субдомены, такие как bozo.za.net, или bozo.au.uk, bozo.msf.ru просто добавьте (za | au | msf) в регулярное выражение.

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

Ответ 9

/[^w{3}\.]([a-zA-Z0-9]([a-zA-Z0-9\-]{0,65}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}/gim

использование этого регулярного выражения javascript игнорирует www и следующую точку, сохраняя целостность домена. также не соответствует никаким www и cc tld

Ответ 10

Это невозможно без использования списка TLD для сравнения, поскольку в их существовании существует много случаев, таких как http://www.db.de/ или http://bbc.co.uk/

Но даже с этим у вас не будет успеха в каждом случае из-за SLD, например http://big.uk.com/ или http://www.uk.com/

Если вам нужен полный список, вы можете использовать открытый список суффиксов:

http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1

Не стесняйтесь расширять мою функцию только для извлечения имени домена. Он не будет использовать регулярное выражение и быстро:

http://www.programmierer-forum.de/domainnamen-ermitteln-t244185.htm#3471878

Ответ 11

Вам нужно указать, какие префиксы и суффиксы домена можно удалить. Например:

Приставки:

  • www.

суффиксы:

  • .com
  • .co.in
  • .au.uk

Ответ 12

Итак, если у вас есть только строка, а не window.location, вы можете использовать...

String.prototype.toUrl = function(){

if(!this && 0 < this.length)
{
    return undefined;
}
var original = this.toString();
var s = original;
if(!original.toLowerCase().startsWith('http'))
{
    s = 'http://' + original;
}

s = this.split('/');

var protocol = s[0];
var host = s[2];
var relativePath = '';

if(s.length > 3){
    for(var i=3;i< s.length;i++)
    {
        relativePath += '/' + s[i];
    }
}

s = host.split('.');
var domain = s[s.length-2] + '.' + s[s.length-1];    

return {
    original: original,
    protocol: protocol,
    domain: domain,
    host: host,
    relativePath: relativePath,
    getParameter: function(param)
    {
        return this.getParameters()[param];
    },
    getParameters: function(){
        var vars = [], hash;
        var hashes = this.original.slice(this.original.indexOf('?') + 1).split('&');
        for (var i = 0; i < hashes.length; i++) {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }
        return vars;
    }
};};

Как использовать.

var str = "http://en.wikipedia.org/wiki/Knopf?q=1&t=2";
var url = str.toUrl;

var host = url.host;
var domain = url.domain;
var original = url.original;
var relativePath = url.relativePath;
var paramQ = url.getParameter('q');
var paramT = url.getParamter('t');

Ответ 13

С определенной целью я сделал эту быструю функцию Python вчера. Он возвращает домен из URL. Это быстро и не нуждается в каких-либо файлах ввода файлов. Тем не менее, я не притворяюсь, что он работает во всех случаях, но он действительно выполняет работу, требуемую для простого интеллектуального интеллектуального анализа script.

Результат выглядит следующим образом:

http://www.google.co.uk = > google.co.uk
http://24.media.tumblr.com/tumblr_m04s34rqh567ij78k_250.gif = > tumblr.com

def getDomain(url):    
        parts = re.split("\/", url)
        match = re.match("([\w\-]+\.)*([\w\-]+\.\w{2,6}$)", parts[2]) 
        if match != None:
            if re.search("\.uk", parts[2]): 
                match = re.match("([\w\-]+\.)*([\w\-]+\.[\w\-]+\.\w{2,6}$)", parts[2])
            return match.group(2)
        else: return ''  

Кажется, что он работает очень хорошо. Однако он должен быть изменен для удаления расширений домена на выходе по вашему желанию.

Ответ 14

Используйте это (.) (. *?) (.) затем просто извлеките ведущую и конечную точки. Легко, правильно?

Ответ 15

  • как это

    =((?:(?:(?:http)s?:)?\/\/)?(?:(?:[a-zA-Z0-9]+)\.?)*(?:(?:[a-zA-Z0-9]+))\.[a-zA-Z0-9]{2,3}) (вы можете добавить "\/" в конец шаблона

  • если ваша цель состоит в том, чтобы удалить url, переданный в качестве параметра, вы можете добавить знак равенства как первый char, например:

    = (? (:(:(?: HTTP) с:?)//)? (?: (?: [A-Za-Z0-9] +).??) * (:(?:. [A-Za-Z0-9] +)) [A-Za-Z0-9] {2,3}/)

    и замените на "/"

Цель этого примера - избавиться от любого имени домена независимо от формы, в которой он появляется. (то есть для обеспечения того, чтобы параметры URL не включали имена доменов, чтобы избежать атаки xss)

Ответ 16

#!/usr/bin/perl -w
use strict;

my $url = $ARGV[0];
if($url =~ /([^:]*:\/\/)?([^\/]*\.)*([^\/\.]+)\.[^\/]+/g) {
  print $3;
}

Ответ 17

/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/i

Ответ 18

Только для знания:

'http://api.livreto.co/books'.replace(/^(https?:\/\/)([a-z]{3}[0-9]?\.)?(\w+)(\.[a-zA-Z]{2,3})(\.[a-zA-Z]{2,3})?.*$/, '$3$4$5');

# returns livreto.co