Przetwarzanie domeny z adresu URL

144

Muszę zbudować funkcję, która analizuje domenę z adresu URL.

Więc z

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

lub

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

powinien wrócić google.com

z

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

powinien powrócić google.co.uk.

zuk1
źródło
9
@LightnessRacesinOrbit To trochę więcej niż tylko „szukanie w instrukcji”. PHP parse_url()zwraca hosta , a nie domenę .
MrWhite
1
@ w3dk: To nadal byłby fantastyczny punkt wyjścia, pozwalając na to, aby pytanie dotyczyło parse_urlraczej tego ograniczenia niż niejasnego „co mogę zrobić”.
Wyścigi lekkości na orbicie
5
@LightnessRacesinOrbit Twoja obrona jest nieszczera, biorąc pod uwagę twoją reputację - prościej możesz przyznać, że nie przeczytałeś całkowicie pytania
Andy Jones
4
@LightnessRacesinOrbit Niekoniecznie. support.suso.com/supki/…
Jesień Leonard

Odpowiedzi:

297

Sprawdź parse_url():

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

parse_url nie radzi sobie zbyt dobrze z bardzo źle zniekształconymi adresami URL, ale jest w porządku, jeśli generalnie oczekujesz przyzwoitych adresów URL.

piekarnik
źródło
35
Jedną rzeczą, której parse_url () nie robi, jest zwrócenie tylko domeny. Jeśli dodasz www.google.com lub www.google.co.uk, zwróci to również hosta. Jakieś sugestie?
Gavin M. Roy,
6
parse_urlnie obsługuje subdomen, ale Purl tak: github.com/jwage/purl
Damien
1
parse_url()prawdopodobnie przeanalizowałby adresy URL z domeną zawierającą myślniki. Nie udało się znaleźć konkretnego dowodu, ale sprawdź ten błąd . FILTER_VALIDATE_URLużywa parse_url()wewnętrznie.
XedinUnknown
8
Lub po prostu: print parse_url($url, PHP_URL_HOST))jeśli nie potrzebujesz $parsetablicy do niczego innego.
rybo111
98
$domain = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));

Spowoduje to zwrócenie google.comzarówno adresu http://google.com/ ..., jak i http://www.google.com/ ...

Alix Axel
źródło
18
ponieważ nadal zwróci serwer, jeśli wpiszesz „server.google.com” lub „www3.google.com” ...
patrick
Nie wszystkie subdomeny to www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com to tylko kilka przykładów.
rafark
23

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

z jakiegoś dziwnego powodu parse_url zwraca hosta (np. example.com) jako ścieżkę, gdy w wejściowym adresie URL nie podano schematu. Napisałem więc szybką funkcję, aby uzyskać prawdziwy 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 
philfreo
źródło
Nie zapomnij cytować swoich ciągów znaków, takich jak hosti path.
Gumbo
1
Jeśli używam example.com, php wyświetla powiadomienie: czy są Message: Undefined index: hostjakieś pomysły, jak to naprawić?
Zim3r
1
Niestety subdomena jest nadal uwzględniona w tym podejściu, zobacz przykład # 3.
jenlampton
1
@ Zim3r Zmień pierwszą część trójskładnika na !empty($parseUrl['host']).
Demonslay335
LOL, jeśli nie ma schematu, nie jest adresem URL.
miken32
12

Kod, który miał działać w 100%, nie wydawał mi się wystarczający, poprawiłem trochę przykład, ale znalazłem kod, który nie pomagał i problemy z nim. więc zmieniłem to na kilka funkcji (aby oszczędzić ciągłe proszenie o listę z Mozilli i usuwanie systemu pamięci podręcznej). Zostało to przetestowane na zestawie 1000 adresów URL i wydaje się, że działa.

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

Następnie użyj tego jak

$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

Wiem, że powinienem był przekształcić to w zajęcia, ale nie miałem czasu.

Shaun
źródło
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
źródło
Dla mnie też nie działa: example.com // Niepoprawnie: pusty ciąg example.com // Poprawnie: example.com www.example.com // Niepoprawnie: pusty ciąg example.com/xyz // Poprawnie: example.com
jenlampton
To świetna odpowiedź i zasługuje na więcej uznania. Po prostu dodaj tę linię jako pierwszą linię w funkcji, a to również rozwiązuje problemy MangeshSathe i jenlampton: if ((substr ($ url, 0, strlen ('http: //')) <> 'http: //' ) && (substr ($ url, 0, strlen ('https: //')) <> 'https: //')) $ url = 'http: //'.$url;
Rick
4

Jeśli chcesz wyodrębnić hosta ze stringa http://google.com/dhasjkdas/sadsdds/sdda/sdads.html, użycie parse_url () jest dla Ciebie akceptowalnym rozwiązaniem.

Ale jeśli chcesz wyodrębnić domenę lub jej części, potrzebujesz pakietu używającego listy sufiksów publicznych . Tak, możesz używać funkcji tekstowych wokół parse_url (), ale czasami da to nieprawidłowe wyniki.

Polecam TLDExtract do analizowania domeny, oto przykładowy kod, który pokazuje różnice:

$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
źródło
Bardzo dziękuję za tę sugestię. Nienawidzę dodawania kolejnej biblioteki za coś, co wydaje się prostym zadaniem, ale potem zobaczyłem następujący cytat z ich pliku readme: „Wszyscy się mylą. Dzielenie na„ ”. a uwzględnienie dwóch ostatnich elementów jest bardzo przydatne tylko wtedy, gdy myślisz o prostych domenach, np. .com. Pomyśl na przykład o przeanalizowaniu forums.bbc.co.uk : powyższa naiwna metoda podziału da Ci „co” jako domenę i „uk” jako TLD zamiast odpowiednio „bbc” i „co.uk”. "
Demonslay335
Wynik dzielenia kropek, a nie to, co chcemy osiągnąć w naszych ukochanych domenach .co.uk, jest w rzeczywistości prawidłowym wynikiem, ponieważ jest to drugi poziom, a Wielka Brytania jest najwyższym poziomem. Webmaster często nie zdaje sobie z tego sprawy.
Chris
4

Zauważyłem, że rozwiązanie @ philfreo (do którego odwołuje się php.net) daje dobre wyniki, ale w niektórych przypadkach wyświetla "zawiadomienie" i komunikat "Ścisłe standardy" php. Tutaj poprawiona wersja tego kodu.

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
źródło
2

Oto kod, który stworzyłem, że 100% znajduje tylko nazwę domeny, ponieważ bierze pod uwagę mozilla sub tlds. Jedyną rzeczą, którą musisz sprawdzić, jest to, jak tworzysz pamięć podręczną tego pliku, więc nie pytaj za każdym razem do Mozilli.

Z jakiegoś dziwnego powodu domen takich jak co.uk nie ma na liście, więc musisz trochę zhakować i dodać je ręcznie. Nie jest to najczystsze rozwiązanie, ale mam nadzieję, że komuś pomoże.

//=====================================================
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
źródło
Powodem, dla którego domeny co.uknie było na liście, było to, że była to lista TLD, a nie domen. Od czasu napisania tej odpowiedzi ccTLD bardzo się zmieniło. W szczególności: „Nowe rejestracje bezpośrednio w domenie .uk są akceptowane przez Nominet od 10 czerwca 2014 r. Od godziny 08:00 czasu BST, jednak istnieje okres rezerwacji dla obecnych klientów, którzy mają już domeny .co.uk, .org.uk, .me.uk , .net.uk, .ltd.uk lub .plc.uk w celu przejęcia odpowiedniej domeny .uk, która będzie działać do godziny 07:59 czasu BST 10 czerwca 2019 r . ” ( Źródło )
ashleedawg
2

Możesz przekazać PHP_URL_HOST do funkcji parse_url jako drugi parametr

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$host = parse_url($url, PHP_URL_HOST);
print $host; // prints 'google.com'
Oleg Matei
źródło
2
Zasadniczo jest to to samo, co odpowiedź powyżej, jednak pytanie wymaga domeny , która niekoniecznie jest taka sama jak hosta .
MrWhite
zobacz komentarz powyżej dotyczący schematu: z jakiegoś dziwnego powodu parse_url zwraca hosta (np. example.com) jako ścieżkę, gdy żaden schemat nie jest podany w wejściowym adresie URL. Napisałem więc szybką funkcję, aby uzyskać prawdziwego hosta:
jenlampton
2

Rozważ zastąpienie zaakceptowanego rozwiązania następującym:

parse_url () zawsze będzie zawierał dowolne subdomeny, więc ta funkcja nie analizuje dobrze nazw domen. Oto kilka przykładów:

$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

Zamiast tego możesz rozważyć to pragmatyczne rozwiązanie. Obejmuje wiele, ale nie wszystkie nazwy domen - na przykład domeny niższego poziomu, takie jak „sos.state.oh.us”, nie są objęte.

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

Wreszcie, Parser domeny PHP Jeremy'ego Kendalla umożliwia przeanalizowanie nazwy domeny z adresu URL. Parser nazwy hosta URI ligi również wykona zadanie.

Kristoffer Bohmann
źródło
Cześć, to jest dobre, ale nie działa z adresami IP. Mimo wszystko świetna robota.
MeCe
1

parse_url nie działa dla mnie. To tylko zwróciło ścieżkę. Przejście do podstaw przy użyciu php5.3 +:

$url  = str_replace('http://', '', strtolower( $s->website));
if (strpos($url, '/'))  $url = strstr($url, '/', true);
Będzie
źródło
1

Zredagowałem dla Ciebie:

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

Wszystkie typy adresów URL (www.domain.ltd, sub1.subn.domain.ltd spowodują: domain.ltd.

NotFound Life
źródło
1

Dodaję tę odpowiedź późno, ponieważ jest to odpowiedź, która pojawia się najczęściej w Google ...

Możesz użyć PHP, aby ...

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

aby przejąć hosta, ale nie domenę prywatną, do której odnosi się host. (Przykład: www.google.co.ukhost, ale google.co.ukjest to domena prywatna)

Aby przejąć domenę prywatną, musisz znać listę publicznych sufiksów, do których można zarejestrować domenę prywatną. Ta lista jest tworzona przez Mozillę pod adresem https://publicsuffix.org/

Poniższy kod działa, gdy tablica publicznych sufiksów została już utworzona. Po prostu zadzwoń

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

z pozostałym kodem ...

// 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
źródło
Zgodnie z moimi testami parse_url potrzebuje dobrze sformułowanego adresu URL. Jeśli podasz po prostu „www.someDomain.com/path”, to zwróci wartość null. Oczekuje więc obecności protokołów (takich jak http lub https).
Andy,
0

Zwykle działa to bardzo dobrze, jeśli wejściowy adres URL nie jest całkowitym śmieciami. Usuwa subdomenę.

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

Przykład

Wejście: http://www2.website.com:8080/some/file/structure?some=parameters

Wynik: website.com

T. Brian Jones
źródło
0

Połączenie odpowiedzi worldofjr i Alix Axel w jedną małą funkcję, która będzie obsługiwać większość przypadków użycia:

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
źródło
to jest ograniczone rozwiązanie
MGE
0
function getTrimmedUrl($link)
{
    $str = str_replace(["www.","https://","http://"],[''],$link);
    $link = explode("/",$str);
    return strtolower($link[0]);                
}
user3263025
źródło
-6

Po prostu użyj jak po ...

<?php
   echo $_SERVER['SERVER_NAME'];
?>
Md. Maruf Hossain
źródło
1
Zakłada się, że serwer jest adresem URL, z którego chcesz pobrać domenę. To nie o to chodzi.
Overcode