Alan adını bir URL'den ayrıştırma


144

Bir URL etki alanını ayrıştıran bir işlev oluşturmak gerekiyor.

Böylece

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

veya

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

geri dönmeli google.com

ile

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

geri dönmeli google.co.uk.



9
@LightnessRacesinOrbit Bu, "kılavuza bakmaktan" biraz daha fazlasıdır. PHP , etki alanını değil ana bilgisayarıparse_url() döndürür .
MrWhite

1
@ w3dk: Bu sorunun hala parse_urlbelirsiz bir "ne yapabilirim" yerine bu sınırlama hakkında olmasına izin veren harika bir başlangıç ​​noktası olurdu .
Yörüngedeki Hafiflik Yarışları

5
@LightnessRacesinOrbit, itibarınız göz önüne alındığında savunmasız - daha basit bir şekilde soruyu tamamen okumadığınızı itiraf edebilirsiniz
Andy Jones

4
@LightnessRacesinOrbit Mutlaka değil. support.suso.com/supki/…
Sonbahar Leonard

Yanıtlar:


297

Çıkış parse_url():

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

parse_url gerçekten kötü bir şekilde karıştırılmış URL'leri çok iyi işlemez, ancak genellikle iyi URL'ler bekliyorsanız iyi olur.


35
Parse_url () işlevinin yapmadığı bir şey yalnızca etki alanını döndürmektir. Www.google.com veya www.google.co.uk eklerseniz, ana bilgisayar da geri döner. Bunun için herhangi bir öneriniz var mı?
Gavin


6
parse_urlalt alan adlarını kullanmayın
Damien

1
parse_url()URL'leri büyük olasılıkla tire içeren bir alan adıyla ayrıştırır. Kesin kanıt bulunamadı, ancak bu hatayı kontrol edin . dahili olarak FILTER_VALIDATE_URLkullanır parse_url().
XedinBilinmeyen

8
Veya basitçe: başka bir şey print parse_url($url, PHP_URL_HOST))için $parsediziye ihtiyacınız yoksa.
rybo111

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

Bu dönecekti google.comikisi için http://google.com/ ... ve http://www.google.com/ ...


18
çünkü "server.google.com" veya "www3.google.com" ifadelerini girerseniz sunucuyu döndürür ...
patrick

Tüm alt alan adları www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com birkaç örnek değildir.
rafark

23

Http://us3.php.net/manual/en/function.parse-url.php#93983 adresinden

bazı tuhaf nedenlerle, parse_url, giriş url'sinde hiçbir şema sağlanmadığında ana bilgisayarı (ör. example.com) yol olarak döndürür. Bu yüzden gerçek ev sahibi almak için hızlı bir işlev yazdım:

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 

Dizelerinizi hostve gibi alıntılar yapmayı unutmayın path.
Gumbo

1
Example.com kullanırsam, php bir uyarı görüntüler: Message: Undefined index: hostbunu düzeltmek için herhangi bir fikir?
Zim3r

1
Ne yazık ki alt alan adı hala bu yaklaşıma dahil edilmiştir, örnek 3'e bakın.
jenlampton

1
@ Zim3r Üçlemenin ilk bölümünü olarak değiştirin !empty($parseUrl['host']).
Demonslay335

LOL bir şemasına sahip değilse, bir URL değildir.
miken32

12

% 100 çalışması gereken kod benim için kesilmiş gibi görünmüyordu, örneği biraz yama yaptım ama yardımcı olmayan ve onunla ilgili olmayan kodlar buldum. bu yüzden birkaç fonksiyonla değiştirdim (listeyi her zaman Mozilla'dan sormak ve önbellek sistemini kaldırmak için). Bu, bir dizi 1000 URL'ye karşı test edildi ve işe yaramış gibi görünüyordu.

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

Sonra şöyle kullanın

$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

Bunu bir sınıfa dönüştürmem gerektiğini biliyorum, ama zamanım yoktu.


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

Benim için de
çalışmaz

Bu harika bir cevap ve daha fazla krediyi hak ediyor. Bu satırı fonksiyonun ilk satırı olarak ekleyin ve MangeshSathe ve jenlampton'un sorunlarını da çözer: if ((substr ($ url, 0, strlen ('http: //')) <> 'http: //' ) && (substr ($ url, 0, strlen ('https: //')) <> 'https: //')) $ url = 'http: //'.$url;
Rick

4

Ana makineyi dizeden ayıklamak istiyorsanız http://google.com/dhasjkdas/sadsdds/sdda/sdads.html, parse_url () kullanımı sizin için kabul edilebilir bir çözümdür.

Ancak etki alanı veya bölümlerini ayıklamak istiyorsanız, Genel Sonek Listesi'ni kullanarak bu pakete ihtiyacınız vardır . Evet, parse_url () ile ilgili dize işlevlerini kullanabilirsiniz, ancak bazen yanlış sonuçlar verir.

Etki alanı ayrıştırma için TLDExtract tavsiye , burada diff gösteren örnek kod:

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

Bu öneri için çok teşekkür ederim. Basit bir görev gibi görünen bir şey için başka bir kütüphane eklemekten nefret ediyorum , ancak daha sonra beniokularının bana uygulandığını gördüm: "Herkes bunu yanlış anlıyor." ve son 2 öğenin alınması, yalnızca basit ör. .com alanlarını düşünüyorsanız uzun bir yol kat eder.Örneğin forums.bbc.co.uk dosyasını ayrıştırın : yukarıdaki saf bölme yöntemi size alan adı olarak 'co' verecektir ve 'uk' yerine 'bbc' ve 'co.uk' yerine 'uk'.
Demonslay335

Sevgili .co.uk alanlarımızda olmasını istediğimiz şey olmasa da noktaları bölmenin sonucu, aslında doğru sonuçtur, co, İngiltere'nin en üst düzey olduğu ikinci bir düzeydir. Webmaster genellikle bunu fark etmez.
Chris

4

@ Philfreo'nun çözümü (php.net referanslıdır) iyi sonuç almak için oldukça iyi olduğunu gördüm ama bazı durumlarda php "uyarı" ve "Sıkı Standartlar" mesajı gösterir. İşte bu kodun sabit bir sürümü.

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

İşte mozilla alt tlds hesaba alır çünkü% 100 sadece etki alanı adını bulur yapılan kod. Kontrol etmeniz gereken tek şey, bu dosyanın önbelleğini nasıl yaptığınızdır, bu nedenle her seferinde mozilla sorgusunu sormazsınız.

Bazı garip nedenlerden ötürü, co.uk gibi etki alanları listede yer almaz, bu nedenle biraz hacklemeniz ve bunları manuel olarak eklemeniz gerekir. Onun değil en temiz çözüm ama umarım birisi yardımcı olur.

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

Alan adının co.uklistede bulunmamasının nedeni, alan adlarının değil TLD'lerin listesiydi. Bu cevap yazıldığından beri ccTLD çok değişti. Dikkat: "Doğrudan .uk altında yeni kayıtlar Nominet tarafından 10 Haziran 2014 08:00 BST tarihinden itibaren kabul edilmiştir, ancak halihazırda .co.uk, .org.uk, .me.uk olan mevcut müşteriler için bir rezervasyon süresi vardır. , .net.uk, .ltd.uk veya .plc.uk alan adını, 10 Haziran 2019'da 07:59 BST tarihine kadar çalışan ilgili .uk alan adını talep etmek için . " ( Kaynak )
ashleedawg

2

PHP_URL_HOST parametresini parse_url işlevine ikinci parametre olarak iletebilirsiniz

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

2
Bu aslında yukarıdaki yanıtla aynıdır, ancak soru, ana bilgisayarla aynı olması gerekmeyen etki alanını gerektirir .
MrWhite

yukarıdaki şema hakkındaki açıklamaya bakınız: bazı tuhaf nedenlerle parse_url, ana makineyi (ör. example.com) giriş url'sinde hiçbir şema sağlanmadığında yol olarak döndürür. Bu yüzden gerçek ev sahibi almak için hızlı bir işlev yazdım:
jenlampton


2

Lütfen kabul edilen çözümü aşağıdaki ile değiştirmeyi düşünün:

parse_url () her zaman herhangi bir alt etki alanını içerecektir, bu nedenle bu işlev etki alanı adlarını çok iyi ayrıştırmaz. İşte bazı örnekler:

$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

Bunun yerine, bu pragmatik çözümü düşünebilirsiniz. Birçok alan adını içerecek, ancak tüm alan adlarını içermeyecektir - örneğin, 'sos.state.oh.us' gibi daha düşük düzeyli alanlar kapsam dahilinde değildir.

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

Son olarak, Jeremy Kendall'ın PHP Etki Alanı Ayrıştırıcısı , bir url'den etki alanı adını ayrıştırmanıza olanak tanır. Lig URI Hostname Parser da işi yapacak.


Merhaba, bu iyi ama IP adresleri ile çalışmıyor. Yine de harika bir iş.
MeCe

1

parse_url benim için çalışmadı. Sadece yolu döndürdü. Php5.3 + kullanarak temel bilgilere geçme:

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

1

Sizin için düzenledim:

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

Her tür url (www.domain.ltd, sub1.subn.domain.ltd ile sonuçlanır: domain.ltd.


1

Bu cevabı geç ekliyorum, çünkü bu Google'da en çok ortaya çıkan cevap ...

PHP'yi kullanarak ...

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

ana bilgisayarı kapmak, ancak ana bilgisayarın başvurduğu özel alan adını almak için. (Örnek www.google.co.ukana bilgisayar, ancak google.co.uközel alan adıdır)

Özel etki alanını kapmak için, biri kamu soneklerinin listesini bilmesine gerek gerekir edebilir özel alanı kaydetmeye. Bu listenin https://publicsuffix.org/ adresinde Mozilla tarafından küratörlüğünü yaptığı görülüyor.

Aşağıdaki kod, bir dizi genel sonek zaten oluşturulmuşsa çalışır. Sadece arayın

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

kalan kodla ...

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

Testlerime göre, parse_url'un iyi biçimlendirilmiş bir URL'ye ihtiyacı var. Sadece 'www.someDomain.com/path' verirseniz null değerini döndürür. Bu yüzden bir protokolün (http veya https gibi) mevcut olmasını bekler.
Andy

0

Girilen URL toplam önemsiz değilse bu genellikle çok iyi çalışır. Alt etki alanını kaldırır.

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

Misal

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

Çıktı: website.com


0

Worldofjr ve Alix Axel'ın cevaplarını çoğu kullanım durumunu ele alacak küçük bir fonksiyonda birleştirmek :

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

Bu sınırlı bir çözümdür
MGE

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


-6

Sadece aşağıdaki gibi kullanın ...

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

1
Bu, sunucunun etki alanını almak istediğiniz url olduğunu varsayar. Konu bu değil.
Aşırıkoddan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.