2008-11-09 10 views
108

Necesito crear una función que analiza el dominio desde una URL.Dominio de análisis de URL en PHP

Así, con

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

o

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

debe devolver google.com

con

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

debe devolver google.co.uk.

+15

-1: No me molesté en mirar en el manual. –

+1

vea este: http://stackoverflow.com/questions/288810/get-the-subdomain-from-a-url/14688913#14688913 –

+7

@LightnessRacesinOrbit Esto es un poco más que solo "mirar en el manual". El '' parse_url() 'de PHP devuelve _host_, no el _dominio_. – MrWhite

Respuesta

215

Salida parse_url():

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

parse_url no maneja URLs realmente mal destrozados muy bien, pero está bien si en general esperan que las direcciones URL decente.

+24

Una cosa que parse_url() no hace es devolver el dominio. Si agrega www.google.com o www.google.co.uk, también devolverá el host. Alguna sugerencia para eso? –

+1

@Crad, http://stackoverflow.com/questions/8272805/how-to-handle-mozillas-top-domain-name-list-with-php – ilhan

+6

'parse_url' no maneja los subdominios, pero Purl lo hace: https: //github.com/jwage/purl – Damien

19

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

por alguna extraña razón, parse_url devuelve el anfitrión (ex. Example.com) como el camino cuando no se proporciona en el esquema de la url de entrada. Por lo que he escrito una función rápida para obtener el verdadero anfitrión:

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 
+0

No olvides citar tus cadenas como 'host' y' path'. – Gumbo

+0

acaba de copiarlo como está del comentario de php.net, pero hecho ahora – philfreo

+1

Si uso example.com, php muestra un aviso: 'Mensaje: índice indefinido: host' ¿Alguna idea para solucionar esto? – Zim3r

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

Esto devolvería el google.com tanto para http://google.com/ ... y ... http://www.google.com/

+0

¿Por qué tantos downvotes? ¿Hay algo que me estoy perdiendo? –

+9

porque aún devolverá el servidor si ingresa "server.google.com" o "www3.google.com" ... – patrick

3

Aquí es el código que hice que el 100% encuentre solo el nombre de dominio, ya que toma los tlds de mozilla para dar cuenta. Lo único que tiene que comprobar es cómo hace la memoria caché de ese archivo, por lo que no consulta mozilla todo el tiempo.

Por alguna extraña razón, dominios como co.uk no están en la lista, por lo que debe realizar algunas operaciones de piratería y agregarlas manualmente. No es la solución más limpia, pero espero que ayude a alguien.

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

El código que estaba destinado a trabajar 100% no parecía cortarlo para mí, lo hice parchear el ejemplo un poco, pero encontró el código que no estaba ayudando y problemas con él. así que lo cambié a un par de funciones (para guardar preguntando por la lista de mozilla todo el tiempo, y eliminando el sistema cahce). Esto se ha probado en un conjunto de 1000 URL y parecía funcionar.

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

Entonces usarlo como

$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 

Yo sé que debería haber convertido esto en una clase, pero no tuvo tiempo.

1

parse_url no funcionó para mí. Solo devolvió el camino. El cambio a lo básico utilizando PHP5.3 +:

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

¿funciona esto para https? – adam

-1

En general, esto va a funcionar muy bien si la URL de entrada no es basura total. Elimina el subdominio.

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

Ejemplo

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

Salida: website.com

+0

no funciona para los dominios .co.uk – user1398287

0

Aquí mi rastreador basado en las respuestas anteriores.

  1. implementación de la clase (me gusta :) Obj
  2. utiliza Curl por lo que podemos utilizar se requiere autenticación HTTP
  3. lo único vínculo de rastreo que pertenece al dominio de la URL de inicio
  4. se imprime el encabezado HTTP código de respuesta (útil para comprobar problemas en un sitio)

ARRASTRE clase de código

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

Puede pasar PHP_URL_HOST en función parse_url como segundo parámetro

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

Esto es esencialmente lo mismo que la respuesta anterior, sin embargo, la pregunta requiere el dominio _, que no es necesariamente el mismo que el _host_. – MrWhite

+0

vea el comentario anterior sobre el esquema: por algún motivo impar, parse_url devuelve el host (por ejemplo, example.com) como ruta cuando no se proporciona ningún esquema en la url de entrada. Así que escribí una función rápida para obtener el host real: – jenlampton

1

He editado para usted:

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

Todo tipo de URL (www.domain.ltd, sub1.subn.domain.ltd dará como resultado: domain.ltd.

+0

no funciona para los dominios .co.uk. – jenlampton

2
$domain = parse_url($url, PHP_URL_HOST); 
echo implode('.', array_slice(explode('.', $domain), -2, 2)) 
+0

no funciona para http://google.co.uk/dhasjkdas/sadsdds/sdda/sdads.html – jenlampton

7
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 
+0

No funciona para echo get_domain ('http://www.cdl.gr'); //cdl.gr –

+0

No funciona para mí tampoco: example.com // Incorrecto: cadena vacía http://example.com // Correcto: ejemplo.com www.example.com // Incorrecto: cadena vacía http://example.com/xyz // Correcto: ejemplo.com – jenlampton

-5

sólo tiene que utilizar como como seguir ...

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

Esto supone que el servidor es la url desde la que desea recuperar el dominio. Ese no es el caso. – Overcode

-1

La combinación de las respuestas de worldofjr y Alix Axel en una pequeña función que se encargará de la mayoría de los casos de uso:

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 
+0

no funciona para subdominios que no sean www. – jenlampton

+0

esta es la solución limitada – MGE

4

If desea extraer el host de la cadena http://google.com/dhasjkdas/sadsdds/sdda/sdads.html, el uso de parse_url() es una solución aceptable para usted.

Pero si desea extraer el dominio o sus partes, necesita un paquete que use Public Suffix List. Sí, puede usar funciones de cadena alrededor de parse_url(), pero a veces producirá resultados incorrectos.

Recomiendo TLDExtract para el análisis de dominio, aquí está el código de ejemplo que muestran 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' 
+0

Muchas gracias por esta sugerencia. Odio agregar otra biblioteca para lo que _appears_ es una tarea simple, pero luego vi que esta cita en su archivo léame se aplicaba a mí: "Todo el mundo se equivoca. Partiendo en ''. y tomar los 2 últimos elementos es muy útil solo si estás pensando en dominios .com sencillos. Piensa analizando http://forums.bbc.co.uk por ejemplo: el método de división ingenuo anterior te dará 'co' como el dominio y 'uk' como el TLD, en lugar de 'bbc' y 'co.uk' respectivamente ". – Demonslay335

+0

El resultado de dividir puntos mientras que no es lo que queremos que suceda en nuestros queridos dominios .co.uk, en realidad es el resultado correcto, el co es un segundo nivel con uk siendo el nivel superior. Webmaster a menudo no se da cuenta de eso. – Chris

0

estoy añadiendo esta respuesta tardía ya que esta es la respuesta que aparece más en Google ...

Puede usar PHP para ...

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

para agarrar el anfitrión pero no el dominio privado a la que se refiere el anfitrión. (Ejemplo www.google.co.uk es el anfitrión, pero google.co.uk es el dominio privado)

Para hacerse con el dominio privado, debe necesitar conocer la lista de sufijos públicas a las que uno puede registrar un dominio privado. Esta lista es curada por Mozilla al https://publicsuffix.org/

El siguiente código funciona cuando ya se ha creado una matriz de sufijos públicos. Simplemente llame

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

con el código restante ...

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

Según mi prueba, parse_url necesita una URL bien formada. Si solo le das 'www.someDomain.com/path' entonces devolverá nulo. Por lo tanto, espera que haya un protocolo (como http o https). – Andy

2

he encontrado que la solución de @ philfreo (referenciados a partir php.net) es bastante bien para conseguir buen resultado, pero en algunos casos muestra el mensaje "aviso" y "Normas Estrictas" de php. Aquí una versión fija de este código.

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