Memilah domain dari URL

144

Saya perlu membangun fungsi yang mem-parsing domain dari URL.

Jadi, dengan

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

atau

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

itu harus kembali google.com

dengan

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

itu harus kembali google.co.uk.

zuk1
sumber
9
@LightnessRacesinOrbit Ini sedikit lebih dari sekedar "mencari di manual". PHP parse_url()mengembalikan host , bukan domain .
MrWhite
1
@ w3dk: Ini akan tetap menjadi titik awal yang fantastis, memungkinkan pertanyaan ini tentang batasan parse_urldaripada "apa yang bisa saya lakukan".
Lightness Races dalam Orbit
5
@LightnessRacesinOrbit pertahanan Anda tidak jujur ​​mengingat reputasi Anda - lebih sederhana lagi Anda dapat mengakui bahwa Anda tidak membaca pertanyaan sepenuhnya
Andy Jones
4
@LightnessRacesinOrbit Belum tentu. support.suso.com/supki/…
Autumn Leonard

Jawaban:

297

Lihat parse_url():

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

parse_url tidak menangani url yang benar-benar rusak sangat baik, tetapi baik-baik saja jika Anda biasanya mengharapkan url yang layak.

Owen
sumber
35
Satu hal yang tidak dilakukan parse_url () adalah hanya mengembalikan domain. Jika Anda menambahkan www.google.com atau www.google.co.uk, itu akan mengembalikan tuan rumah juga. Ada saran untuk itu?
Gavin M. Roy
6
parse_urltidak menangani subdomain, tetapi Purl melakukannya: github.com/jwage/purl
Damien
1
parse_url()mungkin akan mem-parsing URL dengan domain yang mengandung tanda hubung salah. Tidak dapat menemukan bukti yang pasti, tetapi periksa bug ini . FILTER_VALIDATE_URLgunakan secara parse_url()internal.
XedinTidak Diketahui
8
Atau sederhananya: print parse_url($url, PHP_URL_HOST))jika Anda tidak membutuhkan $parsearray untuk hal lain.
rybo111
98
$domain = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));

Ini akan mengembalikan google.comuntuk http://google.com/ ... dan http://www.google.com/ ...

Alix Axel
sumber
18
Karena itu masih akan mengembalikan server jika Anda memasukkan "server.google.com" atau "www3.google.com" ...
patrick
Tidak semua subdomain adalah www, crawl-66-249-66-1.googlebot.com, myblog.blogspot.com adalah beberapa contoh.
rafark
23

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

untuk beberapa alasan aneh, parse_url mengembalikan host (mis. example.com) sebagai path ketika tidak ada skema yang disediakan dalam url input. Jadi saya telah menulis fungsi cepat untuk mendapatkan host nyata:

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
sumber
Jangan lupa mengutip string Anda seperti hostdan path.
Gumbo
1
Jika saya menggunakan example.com, php menampilkan pemberitahuan: Message: Undefined index: hostada ide untuk memperbaikinya?
Zim3r
1
Sayangnya subdomain masih disertakan dengan pendekatan ini, lihat contoh Anda # 3.
jenlampton
1
@ Zim3r Ubah bagian pertama dari terner ke !empty($parseUrl['host']).
Demonslay335
LOL jika tidak memiliki skema, itu bukan URL.
miken32
12

Kode yang dimaksudkan untuk bekerja 100% tampaknya tidak memotongnya untuk saya, saya sedikit menambal contoh tetapi menemukan kode yang tidak membantu dan masalah dengan itu. jadi saya mengubahnya menjadi beberapa fungsi (untuk menyimpan meminta daftar dari Mozilla sepanjang waktu, dan menghapus sistem cache). Ini telah diuji terhadap satu set 1000 URL dan tampaknya berfungsi.

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

Kemudian gunakan seperti

$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

Saya tahu saya seharusnya mengubah ini menjadi kelas, tetapi tidak punya waktu.

Shaun
sumber
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
sumber
Juga tidak berfungsi untuk saya: example.com // Salah: string kosong example.com // Benar: example.com www.example.com // Salah: string kosong example.com/xyz // Benar: example.com
jenlampton
Ini adalah jawaban yang bagus dan layak mendapat pujian. Cukup tambahkan baris ini sebagai baris pertama dalam fungsi dan ini juga memecahkan masalah MangeshSathe dan jenlampton: if ((substr ($ url, 0, strlen ('http: //')) <> 'http: //' ) && (substr ($ url, 0, strlen ('https: //')) <> 'https: //')) $ url = 'http: //'.$url;
Rick
4

Jika Anda ingin mengekstrak host dari string http://google.com/dhasjkdas/sadsdds/sdda/sdads.html , penggunaan parse_url () adalah solusi yang dapat Anda terima.

Tetapi jika Anda ingin mengekstrak domain atau bagian-bagiannya, Anda memerlukan paket yang menggunakan Daftar Sufiks Publik . Ya, Anda dapat menggunakan fungsi string di sekeliling parse_url (), tetapi terkadang hasilnya salah.

Saya merekomendasikan TLDExtract untuk penguraian domain, berikut adalah contoh kode yang menunjukkan 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'
Oleksandr Fediashov
sumber
Terima kasih banyak atas saran ini. Saya benci menambahkan perpustakaan lain untuk apa yang tampaknya menjadi tugas yang sederhana, tetapi kemudian saya melihat kutipan ini pada readme mereka diterapkan pada saya: "Semua orang salah paham. Membagi pada '.' dan mengambil 2 elemen terakhir berjalan jauh hanya jika Anda berpikir sederhana misalnya domain com. Pikirkan parsing forums.bbc.co.uk misalnya: metode pemecahan naif di atas akan memberi Anda 'co' sebagai domain dan 'uk' sebagai TLD, alih-alih 'bbc' dan 'co.uk' masing-masing. "
Demonslay335
Hasil untuk memisahkan titik-titik sementara bukan yang kita inginkan terjadi pada domain .co.uk tercinta kita, sebenarnya adalah hasil yang benar, co menjadi level kedua dengan uk menjadi level teratas. Webmaster sering tidak menyadarinya.
Chris
4

Saya telah menemukan bahwa solusi @ philfreo (dirujuk dari php.net) cukup baik untuk mendapatkan hasil yang baik tetapi dalam beberapa kasus ini menunjukkan pesan "pemberitahuan" dan "Standar Ketat" php. Di sini versi tetap dari kode ini.

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
sumber
2

Berikut adalah kode yang saya buat yang 100% hanya menemukan nama domain, karena dibutuhkan mozilla sub tlds ke akun. Satu-satunya hal yang harus Anda periksa adalah bagaimana Anda membuat cache dari file itu, jadi Anda tidak meminta mozilla setiap kali.

Untuk beberapa alasan aneh, domain seperti co.uk tidak ada dalam daftar, jadi Anda harus melakukan peretasan dan menambahkannya secara manual. Ini bukan solusi terbersih tetapi saya harap ini membantu seseorang.

//=====================================================
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
sumber
Alasan domain co.uktidak ada dalam daftar, adalah karena itu adalah daftar TLD, bukan domain. CcTLD telah banyak berubah sejak jawaban ini ditulis. Khususnya: "Registrasi baru langsung di bawah .uk telah diterima oleh Nominet sejak 10 Juni 2014 08:00 BST, namun ada periode reservasi untuk pelanggan lama yang sudah memiliki .co.uk, .org.uk, .me.uk , .net.uk, .ltd.uk atau .plc.uk domain untuk mengklaim domain .uk yang sesuai, yang berjalan hingga 07:59 BST pada 10 Juni 2019. " ( Sumber )
ashleedawg
2

Anda dapat meneruskan PHP_URL_HOST ke fungsi parse_url sebagai parameter kedua

$url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html';
$host = parse_url($url, PHP_URL_HOST);
print $host; // prints 'google.com'
Oleg Matei
sumber
2
Ini pada dasarnya sama dengan jawaban di atas, namun, pertanyaannya adalah membutuhkan domain , yang belum tentu sama dengan host .
MrWhite
lihat komentar di atas tentang skema: untuk beberapa alasan aneh, parse_url mengembalikan host (mis. example.com) sebagai path ketika tidak ada skema yang disediakan dalam url input. Jadi saya telah menulis fungsi cepat untuk mendapatkan host yang sebenarnya:
jenlampton
2

Harap pertimbangkan untuk mengganti solusi yang diterima dengan yang berikut:

parse_url () akan selalu menyertakan sub-domain, jadi fungsi ini tidak menguraikan nama domain dengan sangat baik. Berikut ini beberapa contohnya:

$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

Sebaliknya, Anda dapat mempertimbangkan solusi pragmatis ini. Ini akan mencakup banyak, tetapi tidak semua nama domain - misalnya, domain tingkat rendah seperti 'sos.state.oh.us' tidak tercakup.

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

Akhirnya, PHP Domain Parser milik Jeremy Kendall memungkinkan Anda untuk menguraikan nama domain dari url. League URI Hostname Parser juga akan melakukan pekerjaan itu.

Kristoffer Bohmann
sumber
Hai, ini bagus tetapi tidak bekerja dengan alamat IP. Tetap saja, kerja bagus.
MeCe
1

parse_url tidak bekerja untuk saya. Itu hanya mengembalikan jalan. Beralih ke dasar menggunakan php5.3 +:

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

Saya telah mengedit untuk Anda:

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

Semua jenis url (www.domain.ltd, sub1.subn.domain.ltd akan menghasilkan: domain.ltd.

NotFound Life
sumber
1

Saya menambahkan jawaban ini terlambat karena ini adalah jawaban yang paling banyak muncul di Google ...

Anda dapat menggunakan PHP untuk ...

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

untuk mengambil host tetapi bukan domain pribadi yang dirujuk oleh host. (Contoh www.google.co.ukadalah tuan rumah, tetapigoogle.co.uk adalah domain pribadi)

Untuk mengambil domain pribadi, Anda harus mengetahui daftar sufiks publik tempat seseorang dapat mendaftarkan domain pribadi. Daftar ini kebetulan dikuratori oleh Mozilla di https://publicsuffix.org/

Kode di bawah ini berfungsi ketika array sufiks publik telah dibuat. Cukup telepon

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

dengan kode yang tersisa ...

// 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
sumber
Sesuai pengujian saya, parse_url membutuhkan URL yang terbentuk dengan baik. Jika Anda hanya memberikan 'www.someDomain.com/path' maka itu akan mengembalikan nol. Jadi ia mengharapkan protokol (seperti http atau https) hadir.
Andy
0

Ini umumnya akan bekerja dengan sangat baik jika URL input bukan sampah total. Ini menghapus subdomain.

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

Contoh

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

Keluaran: website.com

T. Brian Jones
sumber
0

Menggabungkan jawaban dari worldofjr dan Alix Axel menjadi satu fungsi kecil yang akan menangani sebagian besar kasus penggunaan:

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
sumber
ini adalah solusi terbatas
MGE
0
function getTrimmedUrl($link)
{
    $str = str_replace(["www.","https://","http://"],[''],$link);
    $link = explode("/",$str);
    return strtolower($link[0]);                
}
pengguna3263025
sumber
-6

Cukup gunakan seperti berikut ...

<?php
   echo $_SERVER['SERVER_NAME'];
?>
Md. Maruf Hossain
sumber
1
Ini dengan asumsi server adalah url yang ingin Anda ambil domainnya. Bukan itu masalahnya.
Overcode