web-dev-qa-db-fra.com

comment obtenir le nom de domaine depuis l'URL

Comment puis-je récupérer un nom de domaine à partir d'une chaîne d'URL?

Exemples:

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

En relation:

45
Chinmay

Une fois, j’ai dû écrire une telle regex pour une entreprise pour laquelle je travaillais. La solution était la suivante:

  • Obtenez une liste de tous les ccTLD et gTLD disponibles. Votre premier arrêt devrait être IANA . La liste de Mozilla a fière allure à première vue, mais manque par exemple ac.uk, elle n’est donc pas vraiment utilisable.
  • Rejoignez la liste comme dans l'exemple ci-dessous. Un avertissement: Commander est important! Si org.uk apparaît après uk alors exemple.org.uk correspond à org au lieu de exemple

Exemple de regex:

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

Cela a très bien fonctionné et a également correspondu à des niveaux supérieurs non officiels, tels que de.com, et à des amis.

L'avantage:

  • Très rapide si regex est ordonné de manière optimale

L'inconvénient de cette solution est bien entendu:

  • Regex manuscrite qui doit être mis à jour manuellement si les ccTLD sont modifiés ou ajoutés. Travail fastidieux!
  • Très grande regex donc pas très lisible.
39
pi.
/^(?:www\.)?(.*?)\.(?:com|au\.uk|co\.in)$/
12
jfs

Extraire le nom de domaine avec précision peut être assez difficile principalement parce que l'extension de domaine peut contenir 2 parties (comme .com.au ou .co.uk) et que le sous-domaine (le préfixe) peut être ou ne pas être présent. La liste de toutes les extensions de domaine n'est pas une option car il en existe des centaines. EuroDNS.com, par exemple, répertorie plus de 800 extensions de nom de domaine.

J'ai donc écrit une courte fonction php qui utilise 'parse_url ()' et quelques observations sur les extensions de domaine pour extraire avec précision les composants url ET le nom de domaine. La fonction est la suivante:

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

Cette fonction simple fonctionnera dans presque tous les cas. Il y a quelques exceptions, mais elles sont très rares.

Pour démontrer/tester cette fonction, vous pouvez utiliser les éléments suivants:

$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>";

Le résultat sera le suivant pour les URL répertoriées:

 enter image description here

Comme vous pouvez le constater, le nom de domaine et le nom de domaine sans l'extension sont systématiquement extraits, quelle que soit l'URL présentée à la fonction.

J'espère que ca aide.

8
Clinton

Je ne connais aucune bibliothèque, mais la manipulation des noms de domaine par des chaînes est assez simple. 

La partie difficile est de savoir si le nom est au deuxième ou au troisième niveau. Pour cela, vous aurez besoin d’un fichier de données que vous conservez (par exemple, car .uk n’est pas toujours le troisième niveau, certaines organisations (par exemple, bl.uk, jet.uk) existent au deuxième niveau).

La source de Firefox de Mozilla contient un tel fichier de données. Vérifiez les licences de Mozilla pour voir si vous pouvez le réutiliser.

4
Richard

Il y a deux façons

Utilisation de split

Ensuite, il suffit d'analyser cette chaîne

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

Utiliser Regex

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

J'espère que cela t'aides

4
Fizer Khan
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])

Ce code n'est pas garanti pour fonctionner avec toutes les URL et ne filtre pas celles qui sont grammaticalement correctes mais non valides, comme 'exemple.uk'. 

Cependant, cela fera le travail dans la plupart des cas.

3
Juan-Pablo Scaletti

Il n’est pas possible sans utiliser une liste de TLD avec laquelle il existe de nombreux cas comme http://www.db.de/ ou http://bbc.co.uk/ qui sera interprété par une expression rationnelle comme les domaines db.de (correct) et co.uk (faux).

Mais même avec cela, vous ne réussirez pas si votre liste ne contient pas de SLD également. Des URL du type http://big.uk.com/ et http://www.uk.com/ seraient toutes deux interprétées comme uk.com (le premier domaine est big.uk.com).

Pour cette raison, tous les navigateurs utilisent la liste des suffixes publics de Mozilla:

https://en.wikipedia.org/wiki/Public_Suffix_List

Vous pouvez l'utiliser dans votre code en l'important via cette URL: 

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

N'hésitez pas à étendre ma fonction pour extraire le nom de domaine uniquement. Il n'utilisera pas de regex et c'est rapide:

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

2
mgutt

En gros, ce que vous voulez, c'est:

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

Optionnel:

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

Vous n'avez pas besoin de construire une regex en constante évolution, car 99% des domaines seront correctement mis en correspondance si vous regardez simplement la 2e dernière partie du nom:

(co|com|gov|net|org)

Si c'est l'un de ceux-ci, vous devez faire correspondre 3 points, sinon 2. Simple. Maintenant, ma magie des expressions rationnelles ne peut pas rivaliser avec celle de certains autres SO, donc la meilleure façon que j'ai trouvée d'y parvenir est d'utiliser du code, en supposant que vous ayez déjà tracé le chemin:

 my @d=split /\./,$domain;                # split the domain part into an array
 $c=@d;                                   # 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

Pour obtenir juste le nom, selon votre question:

 my @d=split /\./,$domain;                # split the domain part into an array
 $c=@d;                                   # 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

J'aime cette approche car elle ne nécessite aucun entretien. Sauf si vous voulez valider qu'il s'agit bien d'un domaine légitime, mais c'est un peu inutile, car vous ne l'utilisez probablement que pour traiter les fichiers journaux et un domaine non valide ne s'y retrouverait pas.

Si vous souhaitez faire correspondre des sous-domaines "non officiels" tels que bozo.za.net ou bozo.au.uk, bozo.msf.ru ajoutez simplement (za | au | msf) à l'expression régulière.

J'adorerais voir quelqu'un faire tout cela en utilisant une simple expression régulière, je suis sûr que c'est possible.

2
dagelf

Utilisez ceci (.) (. *?) (.) Puis extrayez simplement les points d’avant et de fin. Facile, non?

0
pabben
  1. comment est-ce

    =((?:(?:(?:http)s?:)?\/\/)?(?:(?:[a-zA-Z0-9]+)\.?)*(?:(?:[a-zA-Z0-9]+))\.[a-zA-Z0-9]{2,3}) (vous pouvez ajouter "\ /" à la fin du modèle

  2. si votre but est de supprimer les URLs transmises en tant que param, vous pouvez ajouter le signe égal en tant que premier caractère, comme ceci:

    = ((? :(? :(?: http) s?:)? //)? (?: (?: [a-zA-Z0-9] +).?) * (?: (?: [ a-zA-Z0-9] +)). [a-zA-Z0-9] {2,3} /)

    et remplacez par "/"

Le but de cet exemple est de se débarrasser de tout nom de domaine, quel que soit le formulaire sous lequel il apparaît dans .

0
Chaim Klar

Vous avez besoin d'une liste des préfixes et suffixes de domaine pouvant être supprimés. Par exemple:

Préfixes:

  • www.

Suffixes:

  • .com
  • .co.in
  • .au.uk
0
Gumbo

Dans un but précis, j’ai réalisé cette rapide fonction Python hier. Il retourne le domaine de l'URL. C'est rapide et ne nécessite aucune liste de fichiers d'entrée. Cependant, je ne prétends pas que cela fonctionne dans tous les cas, mais cela fait vraiment le travail dont j'avais besoin pour un simple script d'exploration de texte.

La sortie ressemble à ceci: 

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 ''  

Semble fonctionner assez bien.
Cependant, il doit être modifié pour supprimer les extensions de domaine en sortie comme vous le souhaitez.

0
binnie

Donc si vous avez juste une chaîne et pas un window.location, vous pouvez utiliser ...

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

Comment utiliser.

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');
0
Thomas Paris