URLからのドメインの解析


144

URLからドメインを解析する関数を作成する必要があります。

だから、

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

または

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

それは戻るはずです google.com

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

戻るはずgoogle.co.ukです。



9
@LightnessRacesinOrbitこれは単に「マニュアルを見る」だけではありません。PHP はドメインではなくホストをparse_url()返します
MrWhite 2016

1
@ w3dk:それは素晴らしい出発点であり続け、この質問をparse_url漠然とした「何ができるか」というよりもその制限についての質問にすることができます。
Orbitのライトネスレース2016年

5
@LightnessRacesinOrbitあなたの評判を考えると、防御は不誠実です-より簡単に言えば、質問を完全に読んでいないことを認めることができます
Andy Jones

4
@LightnessRacesinOrbit必ずしもそうではありません。support.suso.com/supki/...
秋のレナード

回答:


297

チェックアウトparse_url()

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

parse_url 本当にひどく壊れたURLをうまく処理しませんが、一般的にまともなURLを期待している場合は問題ありません。


35
parse_url()が行わないことの1つは、ドメインを返すことだけです。www.google.comまたはwww.google.co.ukを追加すると、ホストも返されます。そのための提案はありますか?
ギャビンM.ロイ


6
parse_urlサブドメインは処理しませんが、Purl
Damien

1
parse_url()ダッシュが誤って含まれているドメインでURLを解析する可能性があります。明確な証拠は見つかりませんでしたが、このバグを確認してください。内部的にFILTER_VALIDATE_URL使用しparse_url()ます。
XedinUnknown 2015

8
または単に:何かのために配列がprint parse_url($url, PHP_URL_HOST))必要ない場合$parse
rybo111

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

これは、http://google.com/ ...とhttp://www.google.com/ ...のgoogle.com両方を返します


18
「server.google.com」または「www3.google.com」を入力した場合でもサーバーを返すため...
patrick

すべてのサブドメインがwwwであるとは限りません。crawl-66-249-66-1.googlebot.com、myblog.blogspot.comはいくつかの例です。
rafark

23

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

奇妙な理由により、入力URLにスキームが指定されていない場合、parse_urlはホスト(例:example.com)をパスとして返します。そこで、実際のホストを取得するための簡単な関数を作成しました。

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 

hostandのような文字列を引用することを忘れないでくださいpath
ガンボ

1
example.comを使用すると、phpは通知を表示Message: Undefined index: hostします。これを修正するためのアイデアはありますか?
Zim3r

1
残念ながら、このアプローチにはサブドメインがまだ含まれています。例3を参照してください。
jenlampton 2016年

1
@ Zim3r三項の最初の部分をに変更し!empty($parseUrl['host'])ます。
Demonslay335 2017年

スキームがない場合、それはURLではありません。
miken32

12

100%動作するように意図されたコードは私にとってそれを削減するようには見えませんでした。私は例に少しパッチを当てましたが、役に立たないコードとそれに関する問題を見つけました。そこで、私はそれをいくつかの機能に変更しました(常にMozillaからリストを要求することを節約し、キャッシュシステムを削除するため)。これは、1000のURLのセットに対してテストされ、機能しているようです。

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

次に、それを次のように使用します

$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

これをクラスにすべきだったのは分かっていましたが、時間がありませんでした。


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

example.com //正しくない:空の文字列example.com //正しい:example.com www.example.com //正しくない:空の文字列example.com/xyz //正しい:example.com
jenlampton

これは素晴らしい答えであり、より多くの信用に値します。この行を関数の最初の行として追加するだけで、MangeshSatheとjenlamptonの問題も解決されます。if((substr($ url、0、strlen( 'http://'))<> 'http://' )&&(substr($ url、0、strlen( 'https://'))<> 'https://'))$ url = 'http://'.$url;
リック

4

文字列からホストを抽出したい場合 http://google.com/dhasjkdas/sadsdds/sdda/sdads.html、parse_url()の使用が受け入れ可能な解決策です。

ただし、ドメインまたはその一部を抽出する場合は、パブリックサフィックスリストを使用してパッケージ化する必要があります。はい、parse_url()を囲む文字列関数を使用できますが、正しくない結果が生成されることがあります。

ドメインの解析にはTLDExtractをお勧めします。以下は、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'

この提案をありがとうございました。簡単な作業のように見える別のライブラリを追加するのは嫌いですが、readmeに次のような引用が適用されているのを目にしました。そして、最後の2つの要素を取ることは、単純な例(.comドメインなど)を考えている場合にのみ、長い道のりになります。たとえば、forums.bbc.co.ukの解析を考えてみてください。TLDとしての「uk」は、「bbc」と「co.uk」のそれぞれではありません。」
Demonslay335 2017年

私たちの愛する.co.ukドメインで起こりたいことではないが、ドットを分割した結果は実際には正しい結果です。coは第2レベルで、ukはトップレベルです。多くの場合、ウェブマスターはそれを認識していません。
Chris

4

私は@philfreoの解決策(php.netから参照)が適切な結果を得るにはかなり良いことを発見しましたが、場合によっては、phpの「通知」および「厳密な標準」メッセージが表示されます。ここにこのコードの修正バージョンがあります。

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

これは、mozilla sub tldsを考慮に入れるため、100%がドメイン名のみを検出するように作成したコードです。確認する必要があるのは、そのファイルのキャッシュを作成する方法だけなので、毎回mozillaをクエリする必要はありません。

奇妙な理由で、co.ukのようなドメインはリストにないため、ハッキングを行って手動で追加する必要があります。その最もクリーンなソリューションではありませんが、誰かを助けることを願っています。

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

ドメインco.ukがリストになかった理由は、ドメインではなくTLDのリストだったからです。この回答が書かれてから、ccTLDは大幅に変更されました。特に:「.uk直下の新規登録は、2014年6月10日08:00 BST以降、Nominetによって受け入れられましたが、すでに.co.uk、.org.uk、.me.ukを持っている既存のお客様には予約期間があります。 、.net.uk、.ltd.uk、または.plc.ukドメインは、対応する.ukドメインを要求します。これは、2019年6月10日の BST 07:59まで実行されます。」(出典
ashleedawg 2018

2

PHP_URL_HOSTを2番目のパラメーターとしてparse_url関数に渡すことができます

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

2
これは基本的に上記の回答と同じですが、問題はドメインを必要とすることですドメインは必ずしもホストと同じであるとは限りません。
MrWhite

スキームに関する上記のコメントを参照してください:奇妙な理由で、入力URLにスキームが指定されていない場合、parse_urlはホスト(例:example.com)をパスとして返します。そこで、実際のホストを取得するための簡単な関数を作成しました
。– jenlampton


2

承認済みのソリューションを次のように置き換えることを検討してください:

parse_url()には常にサブドメインが含まれるため、この関数はドメイン名を適切に解析しません。ここではいくつかの例を示します。

$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

代わりに、この実用的なソリューションを検討できます。すべてではありませんが、多くのドメイン名がカバーされます。たとえば、「sos.state.oh.us」などの下位レベルのドメインはカバーされません。

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

最後に、Jeremy KendallのPHPドメインパーサーを使用すると、URLからドメイン名を解析できます。リーグURIホスト名パーサーも仕事をします。


こんにちは、これは良いことですが、IPアドレスでは機能しません。それでも素晴らしい仕事です。
MeCe

1

parse_urlが機能しませんでした。パスのみを返しました。php5.3 +を使用して基本に切り替える:

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

1

私はあなたのために編集しました:

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

すべてのタイプのURL(www.domain.ltd、sub1.subn.domain.ltdは次のようになります:domain.ltd。


1

これはグーグルで最もよく現れる答えなので、私はこの答えを遅く追加しています...

PHPを使用して...

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

ホストを取得しますが、ホストが参照するプライベートドメインは取得しません。(例www.google.co.ukはホストgoogle.co.ukですが、プライベートドメインです)

プライベートドメインを取得するには、プライベートドメイン登録できるパブリックサフィックスのリストを知っている必要があります。このリストは、https: //publicsuffix.org/のMozillaによってキュレートされています。

以下のコードは、パブリックサフィックスの配列が既に作成されている場合に機能します。単に電話する

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

残りのコードで...

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

私のテストによると、parse_urlには整形式のURLが必要です。「www.someDomain.com/path」だけを指定すると、nullが返されます。したがって、プロトコル(httpやhttpsなど)が存在することを想定しています。
アンディ

0

これは、入力URLが完全に迷惑メールではない場合、通常は非常にうまく機能します。サブドメインを削除します。

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

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

出力: website.com


0

worldofjrAlix Axelの答えを、ほとんどのユースケースを処理する1つの小さな関数に結合します。

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

これは限定的なソリューションです
MGE 2017年

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


-6

以下のように使うだけで......

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

1
これは、サーバーがドメインを取得するURLであると想定しています。そうではありません。
15年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.