2008-11-13 39 views
93

Obtener el subdominio desde una URL parece fácil al principio.Obtiene el subdominio desde una URL

http://www.domain.example 

Scan para el primer período luego regresar lo que vino después de "http: //" ...

Entonces recuerde

http://super.duper.domain.example 

Oh. Entonces piensas, está bien, ¡encuentra el último período, retrocede una palabra y obtén todo antes!

continuación, recordar

http://super.duper.domain.co.uk 

y ya está de vuelta al punto de partida. ¿Alguien tiene alguna idea genial además de almacenar una lista de todos los TLD?

+0

Cam aclaras lo que quieres? Parece que buscas la parte del dominio "oficial" de la URL (es decir, domain.co.uk), independientemente de cuántas etiquetas DNS aparezcan antes de ella. – Alnitak

+0

Estoy de acuerdo. Expande más sobre cuál es tu objetivo final. – BuddyJoe

+0

Esta pregunta ya se ha formulado aquí: [Obtención de partes de una URL] (http://stackoverflow.com/questions/27745/getting-parts-of-a-url-regex) Editar: se ha formulado una pregunta similar aquí:) –

Respuesta

64

¿Alguien tiene alguna idea genial además de almacenando una lista de todos los TLD?

No, porque cada TLD difiere de lo que se considera un subdominio, dominio de segundo nivel, etc.

Tenga en cuenta que hay dominios de nivel superior, dominios de segundo nivel, y subdominios. Técnicamente hablando, todo excepto el TLD es un subdominio.

En el ejemplo de domain.com.uk, el dominio es un subdominio, com es un dominio de segundo nivel y uk es el tld.

Por lo tanto, la pregunta sigue siendo más compleja que a primera vista, y depende de cómo se gestione cada TLD. Necesitará una base de datos de todos los TLD que incluyan su partición particular, y lo que cuenta como un dominio de segundo nivel y un subdominio. Sin embargo, no hay demasiados TLD, por lo que la lista es razonablemente manejable, pero recopilar toda esa información no es trivial. Es posible que ya haya una lista disponible.

Parece que http://publicsuffix.org/ es una de esas listas, todos los sufijos comunes (.com, .co.uk, etc.) en una lista adecuada para la búsqueda. Todavía no será fácil analizarlo, pero al menos no tienes que mantener la lista.

A "sufijo público" es una virtud de la cual usuarios de Internet pueden registrarse directamente nombres. Algunos ejemplos de sufijos públicos son ".com", ".co.uk" y "pvt.k12.wy.us". La lista Sufijo público es una lista de todos los sufijos públicos conocidos .

La lista de sufijos públicos es una iniciativa de la Fundación Mozilla. Está disponible para su uso en cualquier software , pero fue creado originalmente para satisfacer las necesidades de los fabricantes de navegadores .Permite a los navegadores a, por ejemplo:

  • Evitar la privacidad dañar "SuperCookies" que se establezca para el nombre de dominio alto nivel sufijos
  • Resalte la parte más importante de un nombre de dominio en el usuario interfaz
  • ordenar las entradas del historial con precisión por el sitio

Looking through the list, se puede ver que no es un problema trivial. Creo que una lista es la única forma correcta de lograr esto ...

-Adam

+2

excelente - Menciono publicsuffix.org primero ¡y todos los demás obtienen los puntos de rep.!Recomiendo a cualquiera que lea esto leer el borrador del IETF al que me referí, escrito por un programador de ópera de alto nivel que intenta resolver este problema de manera real. – Alnitak

+0

Mozilla tiene un código que usa este servicio. El proyecto se escindió porque la especificación original de las cookies había vinculado los TLD para confiar en las cookies, pero nunca funcionó. El error "Cookie Monster" fue el primer problema, y ​​la arquitectura nunca fue reparada o reemplazada. – benc

+0

El idioma preferido para resolver esto no está en la lista, pero hay un proyecto de código abierto que utiliza esta lista en el código C# aquí: http://code.google.com/p/domainname-parser/ –

24

Como dice Adam, que no es fácil, y en la actualidad la única forma práctica es utilizar una lista.

Incluso entonces hay excepciones; por ejemplo, en .uk hay un puñado de dominios que son válidos inmediatamente en ese nivel que no están en .co.uk, por lo que deben agregarse como excepciones.

Así es como los principales navegadores hacen esto - es necesario asegurarse de que example.co.uk no pueda establecer una Cookie para .co.uk que luego se enviaría a cualquier otro sitio web bajo .co.uk.

La buena noticia es que ya hay una lista disponible en http://publicsuffix.org/.

También hay algo de trabajo en el IETF para crear algún tipo de estándar que permita a los TLD declarar cómo es su estructura de dominio. Sin embargo, esto es un poco complicado por los gustos de .uk.com, que se opera como si fuera un sufijo público, pero no se vende en el registro .com.

+1

Eugh, el IETF debería saber mejor que dejar que sus URL mueran. El borrador (actualizado por última vez en septiembre de 2012) ahora puede ser alcanzado aquí: http://tools.ietf.org/html/draft-pettersen-subtld-structure – IMSoP

+0

@IMSoP gracias por el enlace actualizado ... – Alnitak

+0

El grupo de trabajo IETF sobre el tema (DBOUND) ha sido cerrado. –

0

No está funcionando hacia fuera exactamente, pero que tal vez podría obtener una respuesta útil al tratar de buscar la pieza de dominio por pieza y comprobar la respuesta, es decir, ir a buscar 'http://uk', luego 'http://co.uk', luego 'http://domain.co.uk'. Cuando obtiene una respuesta sin errores, obtiene el dominio y el resto es subdominio.

veces sólo hay que probarlo :)

Editar:

Tom Leys señala en los comentarios, que algunos dominios se establecen únicamente en el subdominio www, lo cual nos daría una respuesta incorrecta responder en la prueba anterior. ¡Buen punto! ¿Quizás el mejor enfoque sería verificar cada parte con 'http://www' y 'http: //', y contar un golpe como un acierto para esa sección del nombre de dominio? Todavía nos faltarán algunos arreglos 'alternativos' como 'web.domain.com', pero no me he encontrado con ninguno de ellos por un tiempo :)

+0

No hay garantía de que x.com apunte a un servidor web en el puerto 80, incluso si lo hace en www.x.com. www es un subdominio válido en este caso. Tal vez un whois automatizado ayudaría aquí. –

+0

¡Buen punto! Un whois lo aclararía, aunque manteniendo una lista de los servidores whois a usar para los que para tld/2nd level significaría resolver el mismo problema para casos límite. – jTresidder

+0

no - whois no es la respuesta aquí – Alnitak

-1

Lista de sufijos comunes (.co.uk, .com, etcétera) para eliminar junto con el http: // y solo tendrá "sub.domain" para trabajar en lugar de "http://sub.domain.suffix", o al menos eso es lo que probablemente haría.

El problema más grande es la lista de posibles sufijos. There's a lot, after all.

-3

Echando un vistazo rápido a publicsuffix.org, parece que puede hacer una aproximación razonable eliminando los tres segmentos finales ("segmento", que significa una sección entre dos puntos) de dominios donde el segmento final tiene dos caracteres, en el supuesto de que es un código de país y se subdividirá aún más. Si el segmento final es "nosotros" y el penúltimo segmento también tiene dos caracteres, elimine los últimos cuatro segmentos. En todos los demás casos, elimine los dos segmentos finales. por ejemplo:

"ejemplo" no es de dos caracteres, por lo que eliminar "domain.example", dejando "www"

"ejemplo "no son dos caracteres, por lo tanto, elimine" domain.example ", dejando" super.duper "

"uk" es dos caracteres (pero no "nosotros"), por lo quite "domain.co.uk", dejando "super.duper"

"nosotros" son dos caracteres y es "nosotros", más "wy" también son dos caracteres, por lo tanto, elimine "pvt.k12.wy.us", dejando "foo".

Tenga en cuenta que, aunque esto funciona para todos los ejemplos que he visto en las respuestas hasta el momento, sigue siendo una aproximación razonable. No es del todo correcto, aunque sospecho que es lo más parecido posible sin hacer/obtener una lista real para usar como referencia.

+0

Un caso de error trivial: compare 'http: // www.bit.ly' a' http: // tla.com.au' – kibibu

+2

Hay muchos casos fallidos. Este es el tipo de navegadores de algoritmos utilizados para probar y usar. No hagas eso, usa el PSL - funciona, y hay bibliotecas para ayudarte. –

21

Publicsuffix.org parece la manera de hacerlo. Hay un montón de implementaciones por ahí para analizar el contenido del archivo publicsuffix archivo de datos de forma sencilla:

+2

¡Pero recuerde que no es solo una cuestión de análisis! Esta lista en Publicsuffix.org es un proyecto no oficial, que está incompleto (por ejemplo, eu.org falta), NO refleja automáticamente las políticas de TLD y puede quedar sin mantenimiento en cualquier momento. – bortzmeyer

+0

Ruby: http://github.com/pauldix/domainatrix – lukmdo

+0

Además, Ruby: [github.com/weppos/public_suffix_service](https://github.com/weppos/public_suffix_service) – fractious

-2
+0

El sitio parece estar inactivo y no funciona parece ser capaz de manejar TLDs como '.info' y'. museo' – Quentin

+0

Disculpe que el sitio web no esté en vivo en ese momento. Le dará una idea general sobre la lógica que utilicé en mi caso. Traté de hacer el más genérico en mi caso, que solo manejará un par de escenarios simples (URL) pero puede cambiar la expresión regular un poco para que se adapte a su escenario. – DotNetInfo

+1

Cuando publica un enlace a un artículo de blog, es normal incluir un breve resumen del método utilizado (especialmente para un artículo que usted escribió) – Justin

0

Uso del UriBuilder continuación, obtener el atributo URIBUilder.host dividirlo en una serie de "" ahora tiene una matriz con el dominio dividido.

1

Acabo de escribir un programa para esto en clojure basado en la información de publicsuffix.org:

https://github.com/isaksky/url_dom

Por ejemplo:

(parse "sub1.sub2.domain.co.uk") 
;=> {:public-suffix "co.uk", :domain "domain.co.uk", :rule-used "*.uk"} 
0
echo tld('http://www.example.co.uk/test?123'); // co.uk 

/** 
* http://publicsuffix.org/ 
* http://www.alandix.com/blog/code/public-suffix/ 
* http://tobyinkster.co.uk/blog/2007/07/19/php-domain-class/ 
*/ 
function tld($url_or_domain = null) 
{ 
    $domain = $url_or_domain ?: $_SERVER['HTTP_HOST']; 
    preg_match('/^[a-z]+:\/\//i', $domain) and 
     $domain = parse_url($domain, PHP_URL_HOST); 
    $domain = mb_strtolower($domain, 'UTF-8'); 
    if (strpos($domain, '.') === false) return null; 

    $url = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1'; 

    if (($rules = file($url)) !== false) 
    { 
     $rules = array_filter(array_map('trim', $rules)); 
     array_walk($rules, function($v, $k) use(&$rules) { 
      if (strpos($v, '//') !== false) unset($rules[$k]); 
     }); 

     $segments = ''; 
     foreach (array_reverse(explode('.', $domain)) as $s) 
     { 
      $wildcard = rtrim('*.'.$segments, '.'); 
      $segments = rtrim($s.'.'.$segments, '.'); 

      if (in_array('!'.$segments, $rules)) 
      { 
       $tld = substr($wildcard, 2); 
       break; 
      } 
      elseif (in_array($wildcard, $rules) or 
        in_array($segments, $rules)) 
      { 
       $tld = $segments; 
      } 
     } 

     if (isset($tld)) return $tld; 
    } 

    return false; 
} 
+1

Nota: es posible que desee guardar en caché las reglas ... – Mike

1

Para una biblioteca C (con generación de la tabla de datos en Python), I escribió http://code.google.com/p/domain-registry-provider/ que es a la vez rápido y eficiente del espacio.

La biblioteca utiliza ~ 30kB para las tablas de datos y ~ 10kB para el código C. No hay sobrecarga de inicio ya que las tablas se construyen en tiempo de compilación. Vea http://code.google.com/p/domain-registry-provider/wiki/DesignDoc para más detalles.

Para comprender mejor el código de generación de tabla (Python), comience aquí: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/registry_tables_generator/registry_tables_generator.py

Para comprender mejor la API de C, ver: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/domain_registry/domain_registry.h

+1

También tengo una C/C++ biblioteca que tiene su propia lista aunque también se compara con la lista publicsuffix.org. Se llama libtld y funciona en Unix y MS-Windows http://snapwebsites.org/project/libtld –

9

Como ya se ha dicho por Adam y John publicsuffix.org es la forma correcta de ir. Pero, si por alguna razón no puede usar este enfoque, aquí hay una heurística basada en una suposición que funciona para el 99% de todos los dominios:

Hay una propiedad que distingue (no todos, pero casi todos) los dominios "reales" de subdominios y TLD y ese es el registro MX del DNS. Puede crear un algoritmo que busque esto: elimine las partes del nombre de host una por una y consulte el DNS hasta que encuentre un registro MX. Ejemplo:

super.duper.domain.co.uk => no MX record, proceed 
duper.domain.co.uk  => no MX record, proceed 
domain.co.uk    => MX record found! assume that's the domain 

Este es un ejemplo en php:

function getDomainWithMX($url) { 
    //parse hostname from URL 
    //http://www.example.co.uk/index.php => www.example.co.uk 
    $urlParts = parse_url($url); 
    if ($urlParts === false || empty($urlParts["host"])) 
     throw new InvalidArgumentException("Malformed URL"); 

    //find first partial name with MX record 
    $hostnameParts = explode(".", $urlParts["host"]); 
    do { 
     $hostname = implode(".", $hostnameParts); 
     if (checkdnsrr($hostname, "MX")) return $hostname; 
    } while (array_shift($hostnameParts) !== null); 

    throw new DomainException("No MX record found"); 
} 
+0

Eso es lo que IETF también está sugiriendo [aquí] (https://tools.ietf.org/html/draft-pettersen -subtld-structure-10 # appendix-B)? –

+1

Incluso [publicsuffix.org dice] (https: // publicsuffix.org/learn /) (vea el sexto párrafo) que la forma correcta de hacerlo es a través del DNS, ¡tal como lo dijo en su respuesta! –

1

Como ya se ha dicho Public Suffix List es sólo una manera de analizar dominio correctamente. Para PHP puedes probar TLDExtract. Aquí es código de ejemplo:

$extract = new LayerShifter\TLDExtract\Extract(); 

$result = $extract->parse('super.duper.domain.co.uk'); 
$result->getSubdomain(); // will return (string) 'super.duper' 
$result->getSubdomains(); // will return (array) ['super', 'duper'] 
$result->getHostname(); // will return (string) 'domain' 
$result->getSuffix(); // will return (string) 'co.uk' 
0

Puede utilizar este lib tld.js: JavaScript API to work against complex domain names, subdomains and URIs.

tldjs.getDomain('mail.google.co.uk'); 
// -> 'google.co.uk' 

Si está recibiendo dominio raíz en el navegador. Puede usar esta lib AngusFu/browser-root-domain.

var KEY = '__rT_dM__' + (+new Date()); 
var R = new RegExp('(^|;)\\s*' + KEY + '=1'); 
var Y1970 = (new Date(0)).toUTCString(); 

module.exports = function getRootDomain() { 
    var domain = document.domain || location.hostname; 
    var list = domain.split('.'); 
    var len = list.length; 
    var temp = ''; 
    var temp2 = ''; 

    while (len--) { 
    temp = list.slice(len).join('.'); 
    temp2 = KEY + '=1;domain=.' + temp; 

    // try to set cookie 
    document.cookie = temp2; 

    if (R.test(document.cookie)) { 
     // clear 
     document.cookie = temp2 + ';expires=' + Y1970; 
     return temp; 
    } 
    } 
}; 

El uso de cookies es complicado.

Cuestiones relacionadas