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.



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.


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/ ...


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 

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.


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

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'

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

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

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'

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.


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

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.


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

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


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

to jest ograniczone rozwiązanie
MGE

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


-6

Po prostu użyj jak po ...

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

1
Zakłada się, że serwer jest adresem URL, z którego chcesz pobrać domenę. To nie o to chodzi.
Overcode
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.