Analysieren der Domain von einer URL

144

Ich muss eine Funktion erstellen, die die Domain von einer URL analysiert.

Also mit

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

oder

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

es sollte zurückkehren google.com

mit

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

es sollte zurückkehren google.co.uk.

zuk1
quelle
9
@LightnessRacesinOrbit Dies ist ein bisschen mehr als nur "im Handbuch suchen". PHPs geben parse_url()den Host zurück , nicht die Domain .
MrWhite
1
@ w3dk: Es wäre immer noch ein fantastischer Ausgangspunkt gewesen, der es dieser Frage erlaubt hätte, sich eher auf diese Einschränkung parse_urlals auf ein vages "Was kann ich tun" zu beziehen .
Leichtigkeitsrennen im Orbit
5
@ LightnessRacesinOrbit Ihre Verteidigung ist unaufrichtig angesichts Ihres Rufs - einfacher können Sie zugeben, dass Sie die Frage nicht vollständig gelesen haben
Andy Jones
4
@LightnessRacesinOrbit Nicht unbedingt. support.suso.com/supki/…
Herbst Leonard

Antworten:

297

Check out parse_url():

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

parse_url geht nicht wirklich gut mit schlecht verstümmelten URLs um, ist aber in Ordnung, wenn Sie im Allgemeinen anständige URLs erwarten.

Owen
quelle
35
Eine Sache, die parse_url () nicht tut, ist nur die Domain zurückzugeben. Wenn Sie www.google.com oder www.google.co.uk hinzufügen, wird auch der Host zurückgegeben. Irgendwelche Vorschläge dafür?
Gavin M. Roy
6
parse_urlBehandle keine Subdomains, aber Purl: github.com/jwage/purl
Damien
1
parse_url()würde möglicherweise URLs mit einer Domain analysieren, die Striche falsch enthält. Konnte keinen eindeutigen Beweis finden, aber sehen Sie sich diesen Fehler an . FILTER_VALIDATE_URLverwendet parse_url()intern.
XedinUnknown
8
Oder einfach: print parse_url($url, PHP_URL_HOST))Wenn Sie das $parseArray für nichts anderes benötigen .
Rybo111
98
$domain = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));

Dies würde google.comsowohl für http://google.com/ ... als auch für http://www.google.com/ ... zurückgeben.

Alix Axel
quelle
18
Weil es immer noch den Server zurückgibt, wenn Sie "server.google.com" oder "www3.google.com" eingeben ...
Patrick
Nicht alle Subdomains sind www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com sind nur einige Beispiele.
Rafark
23

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

Aus irgendeinem Grund gibt parse_url den Host (z. B. example.com) als Pfad zurück, wenn in der Eingabe-URL kein Schema angegeben ist. Also habe ich eine schnelle Funktion geschrieben, um den richtigen Host zu finden:

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 
Philfreo
quelle
Vergessen Sie nicht, Ihre Zeichenfolgen wie hostund zu zitieren path.
Gumbo
1
Wenn ich example.com verwende, zeigt PHP einen Hinweis an: Gibt es Message: Undefined index: hostIdeen, um dies zu beheben?
Zim3r
1
Leider ist die Subdomain immer noch in diesem Ansatz enthalten, siehe Beispiel 3.
Jenlampton
1
@ Zim3r Ändere den ersten Teil des Ternärs in !empty($parseUrl['host']).
Demonslay335
LOL Wenn es kein Schema gibt, ist es keine URL.
miken32
12

Der Code, der zu 100% funktionieren sollte, schien es für mich nicht zu schneiden. Ich habe das Beispiel ein wenig gepatcht, aber Code gefunden, der nicht half und Probleme damit hatte. Deshalb habe ich es in ein paar Funktionen geändert (um zu sparen, dass ich ständig nach der Liste von Mozilla frage und das Cache-System entferne). Dies wurde gegen einen Satz von 1000 URLs getestet und schien zu funktionieren.

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

Dann benutze es wie

$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

Ich weiß, ich hätte daraus eine Klasse machen sollen, hatte aber keine Zeit.

Shaun
quelle
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
Nikmauro
quelle
Auch für mich funktioniert das nicht: example.com // Falsch: leere Zeichenfolge example.com // Richtig: example.com www.example.com // Falsch: leere Zeichenfolge example.com/xyz // Richtig: example.com
jenlampton
Dies ist eine großartige Antwort und verdient mehr Anerkennung. Fügen Sie einfach diese Zeile als erste Zeile in die Funktion ein und sie löst auch die Probleme von MangeshSathe und jenlampton: if ((substr ($ url, 0, strlen ('http: //')) <> 'http: //' ) && (substr ($ url, 0, strlen ('https: //')) <> 'https: //')) $ url = 'http: //'.$url;
Rick
4

Wenn Sie einen Host aus einem String extrahieren möchten http://google.com/dhasjkdas/sadsdds/sdda/sdads.html, ist die Verwendung von parse_url () für Sie eine akzeptable Lösung.

Wenn Sie jedoch die Domäne oder ihre Teile extrahieren möchten, benötigen Sie ein Paket, das die öffentliche Suffixliste verwendet . Ja, Sie können Zeichenfolgenfunktionen um parse_url () verwenden, aber manchmal werden falsche Ergebnisse erzielt.

Ich empfehle TLDExtract für das Domain-Parsing. Hier ist ein Beispielcode, der diff zeigt:

$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'
Oleksandr Fediashov
quelle
Vielen Dank für diesen Vorschlag. Ich hasse es, eine weitere Bibliothek für eine scheinbar einfache Aufgabe hinzuzufügen , aber dann sah ich dieses Zitat in ihrer Readme-Datei, das auf mich zutraf: "Jeder versteht das falsch. Aufteilen auf das '.' und die letzten 2 Elemente zu nehmen ist nur dann ein langer Weg, wenn Sie an einfache zB .com-Domains denken. Denken Sie beispielsweise an das Parsen von forums.bbc.co.uk : Die oben beschriebene naive Aufteilungsmethode gibt Ihnen 'co' als Domain und 'uk' als TLD anstelle von 'bbc' bzw. 'co.uk'. "
Demonslay335
Das Ergebnis für das Aufteilen von Punkten, obwohl es nicht das ist, was wir auf unseren geliebten .co.uk-Domains tun möchten, ist tatsächlich das richtige Ergebnis, wobei die Co eine zweite Ebene ist und Großbritannien die oberste Ebene ist. Webmaster erkennen das oft nicht.
Chris
4

Ich habe festgestellt, dass die Lösung von @ philfreo (von php.net referenziert) ziemlich gut ist, um ein gutes Ergebnis zu erzielen, aber in einigen Fällen zeigt sie die Meldung "Notice" und "Strict Standards" von php. Hier eine feste Version dieses Codes.

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
fatih
quelle
2

Hier ist der Code, den ich gemacht habe, dass 100% nur den Domainnamen findet, da Mozilla-Subtlds berücksichtigt werden. Sie müssen nur überprüfen, wie Sie den Cache dieser Datei erstellen, damit Sie Mozilla nicht jedes Mal abfragen.

Aus irgendeinem seltsamen Grund sind Domains wie co.uk nicht in der Liste enthalten, daher müssen Sie einige Hacking-Aktionen durchführen und sie manuell hinzufügen. Es ist nicht die sauberste Lösung, aber ich hoffe, es hilft jemandem.

//=====================================================
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];
}
Luka
quelle
Der Grund, warum die Domain co.uknicht auf der Liste stand, war, dass es sich um eine Liste von TLDs handelte, nicht um Domains. Die ccTLD hat sich seit dem Schreiben dieser Antwort stark verändert. Insbesondere: "Neuanmeldungen direkt unter .uk wurden von Nominet seit dem 10. Juni 2014 um 08:00 Uhr MEZ akzeptiert. Es besteht jedoch eine Reservierungsfrist für bestehende Kunden, die bereits eine .co.uk, .org.uk, .me.uk haben , .net.uk, .ltd.uk oder .plc.uk Domain, um die entsprechende .uk Domain zu beanspruchen, die bis 07:59 BST am 10. Juni 2019 läuft . " ( Quelle )
Ashleedawg
2

Sie können PHP_URL_HOST als zweiten Parameter an die Funktion parse_url übergeben

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$host = parse_url($url, PHP_URL_HOST);
print $host; // prints 'google.com'
Oleg Matei
quelle
2
Dies entspricht im Wesentlichen der obigen Antwort. Für die Frage ist jedoch die Domäne erforderlich , die nicht unbedingt mit dem Host identisch ist .
MrWhite
Siehe obigen Kommentar zum Schema: Aus irgendeinem Grund gibt parse_url den Host (z. B. example.com) als Pfad zurück, wenn in der Eingabe-URL kein Schema angegeben ist. Also habe ich eine schnelle Funktion geschrieben, um den echten Host zu bekommen:
Jenlampton
2
$domain = parse_url($url, PHP_URL_HOST);
echo implode('.', array_slice(explode('.', $domain), -2, 2))
Michael
quelle
funktioniert nicht für google.de/dhasjkdas/sadsdds/sdda/sdads.html
jenlampton
2

Bitte ersetzen Sie die akzeptierte Lösung durch Folgendes:

parse_url () enthält immer alle Subdomains, daher analysiert diese Funktion Domainnamen nicht sehr gut. Hier sind einige Beispiele:

$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

Stattdessen können Sie diese pragmatische Lösung in Betracht ziehen. Es werden viele, aber nicht alle Domainnamen abgedeckt. Beispielsweise werden untergeordnete Domains wie 'sos.state.oh.us' nicht behandelt.

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

Mit dem PHP Domain Parser von Jeremy Kendall können Sie den Domainnamen anhand einer URL analysieren. League URI Hostname Parser erledigt ebenfalls die Aufgabe.

Kristoffer Bohmann
quelle
Hallo, das ist gut, aber es funktioniert nicht mit IP-Adressen. Trotzdem großartige Arbeit.
MeCe
1

parse_url hat bei mir nicht funktioniert. Es gab nur den Pfad zurück. Mit php5.3 + zu den Grundlagen wechseln:

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

Ich habe für Sie bearbeitet:

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

Alle Typ-URLs (www.domain.ltd, sub1.subn.domain.ltd) ergeben: domain.ltd.

Nicht gefundenes Leben
quelle
1

Ich füge diese Antwort spät hinzu, da dies die Antwort ist, die bei Google am häufigsten auftaucht ...

Sie können PHP verwenden, um ...

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

um den Host zu greifen, aber nicht die private Domain, auf die sich der Host bezieht. (Beispiel www.google.co.ukist der Host, aber google.co.ukdie private Domain)

Um die private Domain zu erhalten, müssen Sie die Liste der öffentlichen Suffixe kennen, für die eine private Domain registriert werden kann . Diese Liste wird zufällig von Mozilla unter https://publicsuffix.org/ kuratiert.

Der folgende Code funktioniert, wenn bereits ein Array öffentlicher Suffixe erstellt wurde. Einfach anrufen

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

mit dem restlichen Code ...

// 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));
}
Andy Jones
quelle
Nach meinen Tests benötigt parse_url eine wohlgeformte URL. Wenn Sie nur 'www.someDomain.com/path' angeben, wird null zurückgegeben. Daher wird erwartet, dass Protokolle (wie http oder https) vorhanden sind.
Andy
0

Dies funktioniert im Allgemeinen sehr gut, wenn die Eingabe-URL nicht Junk ist. Es entfernt die Subdomain.

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

Beispiel

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

Ausgabe: website.com

T. Brian Jones
quelle
0

Kombinieren Sie die Antworten von worldofjr und Alix Axel zu einer kleinen Funktion, die die meisten Anwendungsfälle behandelt:

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
Michael Giovanni Pumo
quelle
Dies ist eine begrenzte Lösung
MGE
0
function getTrimmedUrl($link)
{
    $str = str_replace(["www.","https://","http://"],[''],$link);
    $link = explode("/",$str);
    return strtolower($link[0]);                
}
user3263025
quelle
-6

Verwenden Sie einfach wie folgt ...

<?php
   echo $_SERVER['SERVER_NAME'];
?>
Md. Maruf Hossain
quelle
1
Dies setzt voraus, dass der Server die URL ist, von der Sie die Domain abrufen möchten. Das ist nicht der Fall.
Overcode