Analizzare il dominio da un URL


144

Devo creare una funzione che analizza il dominio da un URL.

Quindi, con

http://google.com/dhasjkdas/sadsdds/sdda/sdads.html

o

http://www.google.com/dhasjkdas/sadsdds/sdda/sdads.html

dovrebbe tornare google.com

con

http://google.co.uk/dhasjkdas/sadsdds/sdda/sdads.html

dovrebbe tornare google.co.uk.



9
@LightnessRacesinOrbit Questo è un po 'più di una semplice "ricerca nel manuale". PHP parse_url()restituisce l' host , non il dominio .
MrWhite,

1
@ w3dk: Sarebbe stato comunque un fantastico punto di partenza, lasciando che questa domanda riguardasse quella limitazione parse_urlpiuttosto che un vago "cosa posso fare".
Razze di leggerezza in orbita

5
@LightnessRacesinOrbita la tua difesa è insignificante data la tua reputazione - più semplicemente puoi ammettere di non aver letto completamente la domanda
Andy Jones

4
@LightnessRacesinOrbit Non necessariamente. support.suso.com/supki/…
Autunno Leonard,

Risposte:


297

Dai un'occhiata parse_url():

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$parse = parse_url($url);
echo $parse['host']; // prints 'google.com'

parse_url non gestisce molto bene gli URL veramente maledetti, ma va bene se generalmente ti aspetti URL decenti.


35
Una cosa che parse_url () non fa è solo restituire il dominio. Se aggiungi www.google.com o www.google.co.uk, verrà restituito anche l'host. Qualche suggerimento per quello?
Gavin M. Roy,


6
parse_urlnon gestisce i sottodomini, ma Purl lo fa: github.com/jwage/purl
Damien,

1
parse_url()potrebbe analizzare gli URL con un dominio che contiene trattini in modo errato. Impossibile trovare la prova definitiva, ma controlla questo errore . FILTER_VALIDATE_URLutilizza parse_url()internamente.
Xedin Sconosciuta il

8
O semplicemente: print parse_url($url, PHP_URL_HOST))se non hai bisogno $parsedell'array per nient'altro.
Rybo111,

98
$domain = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));

Ciò restituirebbe google.comsia per http://google.com/ ... sia per http://www.google.com/ ...


18
perché restituirà comunque il server se inserisci "server.google.com" o "www3.google.com" ...
patrick,

Non tutti i sottodomini sono www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com sono alcuni esempi.
Rafark,

23

Da http://us3.php.net/manual/en/function.parse-url.php#93983

per qualche strana ragione, parse_url restituisce l'host (es. esempio.com) come percorso quando non viene fornito alcun schema nell'URL di input. Quindi ho scritto una funzione rapida per ottenere il vero host:

function getHost($Address) { 
   $parseUrl = parse_url(trim($Address)); 
   return trim($parseUrl['host'] ? $parseUrl['host'] : array_shift(explode('/', $parseUrl['path'], 2))); 
} 

getHost("example.com"); // Gives example.com 
getHost("http://example.com"); // Gives example.com 
getHost("www.example.com"); // Gives www.example.com 
getHost("http://example.com/xyz"); // Gives example.com 

Non dimenticare di citare le tue corde come hoste path.
Gumbo,

1
Se uso example.com, php visualizza un avviso: Message: Undefined index: hostqualche idea per risolvere questo problema?
Zim3r,

1
Sfortunatamente il sottodominio è ancora incluso in questo approccio, vedi il tuo esempio n. 3.
Jenlampton,

1
@ Zim3r Cambia la prima parte del ternario in !empty($parseUrl['host']).
Demonslay335

LOL se non ha uno schema, non è un URL.
miken32

12

Il codice che doveva funzionare al 100% non sembrava tagliarlo per me, ho corretto un po 'l'esempio ma ho trovato codice che non stava aiutando e problemi con esso. così l'ho cambiato in un paio di funzioni (per salvare chiedendo sempre l'elenco da Mozilla e rimuovendo il sistema cache). Questo è stato testato su un set di 1000 URL e sembra funzionare.

function domain($url)
{
    global $subtlds;
    $slds = "";
    $url = strtolower($url);

    $host = parse_url('http://'.$url,PHP_URL_HOST);

    preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
    foreach($subtlds as $sub){
        if (preg_match('/\.'.preg_quote($sub).'$/', $host, $xyz)){
            preg_match("/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/", $host, $matches);
        }
    }

    return @$matches[0];
}

function get_tlds() {
    $address = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';
    $content = file($address);
    foreach ($content as $num => $line) {
        $line = trim($line);
        if($line == '') continue;
        if(@substr($line[0], 0, 2) == '/') continue;
        $line = @preg_replace("/[^a-zA-Z0-9\.]/", '', $line);
        if($line == '') continue;  //$line = '.'.$line;
        if(@$line[0] == '.') $line = substr($line, 1);
        if(!strstr($line, '.')) continue;
        $subtlds[] = $line;
        //echo "{$num}: '{$line}'"; echo "<br>";
    }

    $subtlds = array_merge(array(
            'co.uk', 'me.uk', 'net.uk', 'org.uk', 'sch.uk', 'ac.uk', 
            'gov.uk', 'nhs.uk', 'police.uk', 'mod.uk', 'asn.au', 'com.au',
            'net.au', 'id.au', 'org.au', 'edu.au', 'gov.au', 'csiro.au'
        ), $subtlds);

    $subtlds = array_unique($subtlds);

    return $subtlds;    
}

Quindi usalo come

$subtlds = get_tlds();
echo domain('www.example.com') //outputs: example.com
echo domain('www.example.uk.com') //outputs: example.uk.com
echo domain('www.example.fr') //outputs: example.fr

So che avrei dovuto trasformarlo in una lezione, ma non avevo tempo.


11
function get_domain($url = SITE_URL)
{
    preg_match("/[a-z0-9\-]{1,63}\.[a-z\.]{2,6}$/", parse_url($url, PHP_URL_HOST), $_domain_tld);
    return $_domain_tld[0];
}

get_domain('http://www.cdl.gr'); //cdl.gr
get_domain('http://cdl.gr'); //cdl.gr
get_domain('http://www2.cdl.gr'); //cdl.gr

Non funziona neanche per me: esempio.com // Errato: stringa vuota esempio.com // Corretto: esempio.com www.esempio.com // Errato: stringa vuota esempio.com/xyz // Corretto: esempio.com
jenlampton

Questa è un'ottima risposta e merita più credito. Basta aggiungere questa riga come prima riga nella funzione e risolve anche i problemi di MangeshSathe e jenlampton: if ((substr ($ url, 0, strlen ('http: //')) <> 'http: //' ) && (substr ($ url, 0, strlen ('https: //')) <> 'https: //')) $ url = 'http: //'.$url;
Rick,

4

Se vuoi estrarre l'host dalla stringa http://google.com/dhasjkdas/sadsdds/sdda/sdads.html, l'uso di parse_url () è una soluzione accettabile per te.

Ma se si desidera estrarre il dominio o le sue parti, è necessario il pacchetto che utilizza l'elenco di suffissi pubblici . Sì, puoi usare le funzioni stringa intorno a parse_url (), ma a volte produrrà risultati errati.

Consiglio TLDExtract per l'analisi del dominio, ecco un codice di esempio che mostra diff:

$extract = new LayerShifter\TLDExtract\Extract();

# For 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html'

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';

parse_url($url, PHP_URL_HOST); // will return google.com

$result = $extract->parse($url);
$result->getFullHost(); // will return 'google.com'
$result->getRegistrableDomain(); // will return 'google.com'
$result->getSuffix(); // will return 'com'

# For 'http://search.google.com/dhasjkdas/sadsdds/sdda/sdads.html'

$url = 'http://search.google.com/dhasjkdas/sadsdds/sdda/sdads.html';

parse_url($url, PHP_URL_HOST); // will return 'search.google.com'

$result = $extract->parse($url);
$result->getFullHost(); // will return 'search.google.com'
$result->getRegistrableDomain(); // will return 'google.com'

Grazie mille per questo suggerimento. Odio aggiungere un'altra libreria per quello che sembra essere un compito semplice, ma poi ho visto questa citazione sul loro file Leggimi applicata a me: "Tutti sbagliano. Spaccando sul '.' e prendere gli ultimi 2 elementi fa molta strada solo se stai pensando a domini semplici, ad esempio .com. Pensa ad analizzare forums.bbc.co.uk per esempio: il metodo di suddivisione ingenuo sopra ti darà 'co' come dominio e "uk" come TLD, anziché "bbc" e "co.uk" rispettivamente. "
Demonslay335

Il risultato per dividere i punti mentre non è ciò che vogliamo che accada sui nostri amati domini .it, è in realtà il risultato corretto, essendo il secondo livello con il Regno Unito al primo livello. I webmaster spesso non se ne rendono conto.
Chris,

4

Ho scoperto che la soluzione di @ philfreo (referenziata da php.net) è piuttosto buona per ottenere un buon risultato, ma in alcuni casi mostra il messaggio "avviso" e "Standard rigorosi" di php. Qui una versione fissa di questo codice.

function getHost($url) { 
   $parseUrl = parse_url(trim($url)); 
   if(isset($parseUrl['host']))
   {
       $host = $parseUrl['host'];
   }
   else
   {
        $path = explode('/', $parseUrl['path']);
        $host = $path[0];
   }
   return trim($host); 
} 

echo getHost("http://example.com/anything.html");           // example.com
echo getHost("http://www.example.net/directory/post.php");  // www.example.net
echo getHost("https://example.co.uk");                      // example.co.uk
echo getHost("www.example.net");                            // example.net
echo getHost("subdomain.example.net/anything");             // subdomain.example.net
echo getHost("example.net");                                // example.net

2

Ecco il codice che ho creato che il 100% trova solo il nome di dominio, dal momento che sono necessari mozilla sub tlds per l'account. L'unica cosa che devi controllare è come creare la cache di quel file, quindi non interrogare mozilla ogni volta.

Per qualche strana ragione, domini come co.uk non sono nell'elenco, quindi devi fare un po 'di hacking e aggiungerli manualmente. Non è la soluzione più pulita ma spero che aiuti qualcuno.

//=====================================================
static function domain($url)
{
    $slds = "";
    $url = strtolower($url);

            $address = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';
    if(!$subtlds = @kohana::cache('subtlds', null, 60)) 
    {
        $content = file($address);
        foreach($content as $num => $line)
        {
            $line = trim($line);
            if($line == '') continue;
            if(@substr($line[0], 0, 2) == '/') continue;
            $line = @preg_replace("/[^a-zA-Z0-9\.]/", '', $line);
            if($line == '') continue;  //$line = '.'.$line;
            if(@$line[0] == '.') $line = substr($line, 1);
            if(!strstr($line, '.')) continue;
            $subtlds[] = $line;
            //echo "{$num}: '{$line}'"; echo "<br>";
        }
        $subtlds = array_merge(Array(
            'co.uk', 'me.uk', 'net.uk', 'org.uk', 'sch.uk', 'ac.uk', 
            'gov.uk', 'nhs.uk', 'police.uk', 'mod.uk', 'asn.au', 'com.au',
            'net.au', 'id.au', 'org.au', 'edu.au', 'gov.au', 'csiro.au',
            ),$subtlds);

        $subtlds = array_unique($subtlds);
        //echo var_dump($subtlds);
        @kohana::cache('subtlds', $subtlds);
    }


    preg_match('/^(http:[\/]{2,})?([^\/]+)/i', $url, $matches);
    //preg_match("/^(http:\/\/|https:\/\/|)[a-zA-Z-]([^\/]+)/i", $url, $matches);
    $host = @$matches[2];
    //echo var_dump($matches);

    preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
    foreach($subtlds as $sub) 
    {
        if (preg_match("/{$sub}$/", $host, $xyz))
        preg_match("/[^\.\/]+\.[^\.\/]+\.[^\.\/]+$/", $host, $matches);
    }

    return @$matches[0];
}

Il motivo per cui il dominio co.uknon era nell'elenco era perché era un elenco di TLD, non di domini. Il ccTLD è cambiato molto da quando è stata scritta questa risposta. In particolare: "Le nuove registrazioni direttamente sotto .uk sono state accettate da Nominet dal 10 giugno 2014 alle 08:00 BST, tuttavia esiste un periodo di prenotazione per i clienti esistenti che hanno già un .co.uk, .org.uk, .me.uk , .net.uk, .ltd.uk o .plc.uk per richiedere il dominio .uk corrispondente, che viene eseguito fino alle 07:59 BST del 10 giugno 2019. " ( Fonte )
ashleedawg,

2

È possibile passare PHP_URL_HOST nella funzione parse_url come secondo parametro

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$host = parse_url($url, PHP_URL_HOST);
print $host; // prints 'google.com'

2
Questo è essenzialmente lo stesso della risposta sopra, tuttavia, la domanda richiede il dominio , che non è necessariamente lo stesso dell'host .
MrWhite,

vedi il commento sopra sullo schema: per qualche strana ragione, parse_url restituisce l'host (es. esempio.com) come percorso quando non viene fornito alcun schema nell'URL di input. Quindi ho scritto una funzione rapida per ottenere il vero host:
jenlampton,


2

Si prega di considerare la sostituzione della soluzione accettata con la seguente:

parse_url () includerà sempre tutti i sottodomini, quindi questa funzione non analizza molto bene i nomi di dominio. Ecco alcuni esempi:

$url = 'http://www.google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$parse = parse_url($url);
echo $parse['host']; // prints 'www.google.com'

echo parse_url('https://subdomain.example.com/foo/bar', PHP_URL_HOST);
// Output: subdomain.example.com

echo parse_url('https://subdomain.example.co.uk/foo/bar', PHP_URL_HOST);
// Output: subdomain.example.co.uk

Invece, puoi considerare questa soluzione pragmatica. Coprirà molti, ma non tutti i nomi di dominio - ad esempio, i domini di livello inferiore come 'sos.state.oh.us' non sono coperti.

function getDomain($url) {
    $host = parse_url($url, PHP_URL_HOST);

    if(filter_var($host,FILTER_VALIDATE_IP)) {
        // IP address returned as domain
        return $host; //* or replace with null if you don't want an IP back
    }

    $domain_array = explode(".", str_replace('www.', '', $host));
    $count = count($domain_array);
    if( $count>=3 && strlen($domain_array[$count-2])==2 ) {
        // SLD (example.co.uk)
        return implode('.', array_splice($domain_array, $count-3,3));
    } else if( $count>=2 ) {
        // TLD (example.com)
        return implode('.', array_splice($domain_array, $count-2,2));
    }
}

// Your domains
    echo getDomain('http://google.com/dhasjkdas/sadsdds/sdda/sdads.html'); // google.com
    echo getDomain('http://www.google.com/dhasjkdas/sadsdds/sdda/sdads.html'); // google.com
    echo getDomain('http://google.co.uk/dhasjkdas/sadsdds/sdda/sdads.html'); // google.co.uk

// TLD
    echo getDomain('https://shop.example.com'); // example.com
    echo getDomain('https://foo.bar.example.com'); // example.com
    echo getDomain('https://www.example.com'); // example.com
    echo getDomain('https://example.com'); // example.com

// SLD
    echo getDomain('https://more.news.bbc.co.uk'); // bbc.co.uk
    echo getDomain('https://www.bbc.co.uk'); // bbc.co.uk
    echo getDomain('https://bbc.co.uk'); // bbc.co.uk

// IP
    echo getDomain('https://1.2.3.45');  // 1.2.3.45

Infine, il parser di dominio PHP di Jeremy Kendall ti consente di analizzare il nome di dominio da un URL. Anche il nome host Parser dell'URI della League farà il lavoro.


Ciao, va bene ma non funziona con gli indirizzi IP. Comunque, ottimo lavoro.
MeCe

1

parse_url non ha funzionato per me. Restituiva solo il percorso. Passare alle basi usando php5.3 +:

$url  = str_replace('http://', '', strtolower( $s->website));
if (strpos($url, '/'))  $url = strstr($url, '/', true);

1

Ho modificato per te:

function getHost($Address) { 
    $parseUrl = parse_url(trim($Address));
    $host = trim($parseUrl['host'] ? $parseUrl['host'] : array_shift(explode('/', $parseUrl['path'], 2))); 

    $parts = explode( '.', $host );
    $num_parts = count($parts);

    if ($parts[0] == "www") {
        for ($i=1; $i < $num_parts; $i++) { 
            $h .= $parts[$i] . '.';
        }
    }else {
        for ($i=0; $i < $num_parts; $i++) { 
            $h .= $parts[$i] . '.';
        }
    }
    return substr($h,0,-1);
}

Tutti i tipi di URL (www.domain.ltd, sub1.subn.domain.ltd risulteranno in: domain.ltd.


1

Sto aggiungendo questa risposta in ritardo poiché questa è la risposta che appare più frequentemente su Google ...

Puoi usare PHP per ...

$url = "www.google.co.uk";
$host = parse_url($url, PHP_URL_HOST);
// $host == "www.google.co.uk"

per catturare l' host ma non il dominio privato a cui fa riferimento l'host. (Esempio www.google.co.ukè l'host, magoogle.co.uk è il dominio privato)

Per acquisire il dominio privato, è necessario conoscere l'elenco dei suffissi pubblici a cui è possibile registrare un dominio privato. Questo elenco sembra essere curato da Mozilla presso https://publicsuffix.org/

Il codice seguente funziona quando è già stata creata una matrice di suffissi pubblici. Chiama semplicemente

$domain = get_private_domain("www.google.co.uk");

con il codice rimanente ...

// find some way to parse the above list of public suffix
// then add them to a PHP array
$suffix = [... all valid public suffix ...];

function get_public_suffix($host) {
  $parts = split("\.", $host);
  while (count($parts) > 0) {
    if (is_public_suffix(join(".", $parts)))
      return join(".", $parts);

    array_shift($parts);
  }

  return false;
}

function is_public_suffix($host) {
  global $suffix;
  return isset($suffix[$host]);
}

function get_private_domain($host) {
  $public = get_public_suffix($host);
  $public_parts = split("\.", $public);
  $all_parts = split("\.", $host);

  $private = [];

  for ($x = 0; $x < count($public_parts); ++$x) 
    $private[] = array_pop($all_parts);

  if (count($all_parts) > 0)
    $private[] = array_pop($all_parts);

  return join(".", array_reverse($private));
}

Secondo i miei test, parse_url necessita di un URL ben formato. Se si fornisce semplicemente "www.someDomain.com/path", verrà restituito null. Quindi si aspetta che siano presenti protocolli (come http o https).
Andy,

0

Questo funzionerà generalmente molto bene se l'URL di input non è spazzatura totale. Rimuove il sottodominio.

$host = parse_url( $Row->url, PHP_URL_HOST );
$parts = explode( '.', $host );
$parts = array_reverse( $parts );
$domain = $parts[1].'.'.$parts[0];

Esempio

Ingresso: http://www2.website.com:8080/some/file/structure?some=parameters

Produzione: website.com


0

Combinando le risposte di worldofjr e Alix Axel in un'unica piccola funzione che gestirà la maggior parte dei casi d'uso:

function get_url_hostname($url) {

    $parse = parse_url($url);
    return str_ireplace('www.', '', $parse['host']);

}

get_url_hostname('http://www.google.com/example/path/file.html'); // google.com

questa è una soluzione limitata
MGE

0
function getTrimmedUrl($link)
{
    $str = str_replace(["www.","https://","http://"],[''],$link);
    $link = explode("/",$str);
    return strtolower($link[0]);                
}


-6

Usa come come segue ...

<?php
   echo $_SERVER['SERVER_NAME'];
?>

1
Ciò presuppone che il server sia l'URL da cui si desidera recuperare il dominio. Non è così.
Overcode
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.