在PHP中通过URLparsing域

我需要构build一个从URLparsing域的函数。

所以,

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

检出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,那么parse_url也不错。

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

这将返回google.comhttp://google.com/ …和http://www.google.com/

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

出于某种奇怪的原因,当inputurl中没有提供scheme时,parse_url返回主机(如example.com)作为path。 所以我写了一个快速的函数来获得真正的主机:

 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 

本来打算100%工作的代码似乎并没有为我所用,但是我做了一些补丁,但是find了一些没有帮助的代码和问题。 所以我把它改成了几个函数(为了节省从mozilla一直请求的列表,并删除cahce系统)。 这已经testing了一组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: exmaple.com echo domain('www.example.uk.com') //outputs: exmaple.uk.com echo domain('www.example.fr') //outputs: exmaple.fr 

我知道我应该把它变成一个class,但是没有时间。

 function get_domain($url = SITE_URL) { preg_match("/[a-z0-9\-]{1,63}\.[az\.]{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 

如果要从stringhttp://google.com/dhasjkdas/sadsdds/sdda/sdads.html提取主机,则可以使用parse_url()作为解决scheme。

但是,如果你想提取域或其部分,你需要使用公共后缀列表的包。 是的,你可以使用string函数arround parse_url(),但是它有时会产生不正确的结果。

我build议TLDExtract域parsing,这里是示例代码显示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' 

这里是我所做的代码,100%只find域名,因为它需要mozilla子域帐户。 只有你必须检查的是你如何caching该文件,所以你不要每次查询mozilla。

出于一些奇怪的原因,像co.uk这样的域名不在列表中,所以你必须做一些黑客手动添加它们。 它不是最干净的解决scheme,但我希望它可以帮助别人。

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

您可以将PHP_URL_HOST作为第二个parameter passing给parse_url函数

 $url = 'http://google.com/dhasjkdas/sadsdds/sdda/sdads.html'; $host = parse_url($url, PHP_URL_HOST); print $host; // prints 'google.com' 
 $domain = parse_url($url, PHP_URL_HOST); echo implode('.', array_slice(explode('.', $domain), -2, 2)) 

我发现@ philfreo的解决scheme(从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 

parse_url没有为我工作。 它只返回了path。 切换到基本使用php5.3 +:

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

检出parse_url()

在这里,我的履带式基于上述的答案。

  1. 类实现(我喜欢Obj 🙂
  2. 它使用Curl所以我们可以使用http auth是必需的
  3. 它只抓取属于起始url域的链接
  4. 它打印http头响应代码(用于检查网站上的问题)

CRAWL CLASS CODE

 class crawler { protected $_url; protected $_depth; protected $_host; public function __construct($url, $depth = 5) { $this->_url = $url; $this->_depth = $depth; $parse = parse_url($url); $this->_host = $parse['host']; } public function run() { $this->crawl_page($this->_url, $this->_depth = 5); } public function crawl_page($url, $depth = 5) { static $seen = array(); if (isset($seen[$url]) || $depth === 0) { return; } $seen[$url] = true; list($content, $httpcode) = $this->getContent($url); $dom = new DOMDocument('1.0'); @$dom->loadHTML($content); $this->processAnchors($dom, $url, $depth); ob_end_flush(); echo "CODE::$httpcode, URL::$url <br>"; ob_start(); flush(); // echo "URL:", $url, PHP_EOL, "CONTENT:", PHP_EOL, $dom->saveHTML(), PHP_EOL, PHP_EOL; } public function processAnchors($dom, $url, $depth) { $anchors = $dom->getElementsByTagName('a'); foreach ($anchors as $element) { $href = $element->getAttribute('href'); if (0 !== strpos($href, 'http')) { $path = '/' . ltrim($href, '/'); if (extension_loaded('http')) { $href = http_build_url($url, array('path' => $path)); } else { $parts = parse_url($url); $href = $parts['scheme'] . '://'; if (isset($parts['user']) && isset($parts['pass'])) { $href .= $parts['user'] . ':' . $parts['pass'] . '@'; } $href .= $parts['host']; if (isset($parts['port'])) { $href .= ':' . $parts['port']; } $href .= $path; } } // Crawl only link that belongs to the start domain if (strpos($href, $this->_host) !== false) $this->crawl_page($href, $depth - 1); } } public function getContent($url) { $handle = curl_init($url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE); /* Get the HTML or whatever is linked in $url. */ $response = curl_exec($handle); /* Check for 404 (file not found). */ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if ($httpCode == 404) { /* Handle 404 here. */ } curl_close($handle); return array($response, $httpCode); } } // USAGE $startURL = 'http://YOUR_START_ULR'; $depth = 2; $crawler = new crawler($startURL, $depth); $crawler->run(); 

我为你编辑过

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

所有types的url(www.domain.ltd,sub1.subn.domain.ltd将导致:domain.ltd。

由于这是在Google上popup最多的答案

你可以使用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是私有域名)

要获取私有域,您必须知道可以注册私有域的公共后缀列表。 这个列表正好由Mozilla在https://publicsuffix.org/上进行策划;

下面的代码在已经创build了一个公共后缀数组的时候工作。 只需打电话

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

如果input的URL不是全部垃圾,这通常会工作得很好。 它删除子域。

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

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

输出: website.com

worldofjrAlix Axel的答案结合成一个可以处理大多数用例的小函数:

 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 

就像下面一样使用…

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