Pregunta

Obtener el subdominio de una URL suena fácil al principio.

http://www.domain.example

Escanee durante el primer período y luego devuelva lo que vino después de " http: // " ...

Entonces recuerdas

http://super.duper.domain.example

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

Entonces recuerdas

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

Y vuelves al punto de partida. ¿Alguien tiene alguna idea genial además de almacenar una lista de todos los TLD?

¿Fue útil?

Solución

  

Alguien tiene grandes ideas además de   almacenar una lista de todos los TLD?

No, porque cada TLD difiere en lo que cuenta como 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 dominio.com.uk, " 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 incluyen 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. Puede que ya haya una lista disponible.

Parece que http://publicsuffix.org/ es una de esas listas & # 8212; 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 tiene que mantener la lista.

  

A '' sufijo público '' es uno bajo el cual   Los usuarios de Internet pueden registrarse directamente   nombres Algunos ejemplos de publico   los sufijos son " .com " ;, " .co.uk " y   `` pvt.k12.wy.us ''. El sufijo público   Lista es una lista de todos los públicos conocidos   sufijos.

     

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

     
      
  • Evite las supercookies que dañan la privacidad estar preparado para   sufijos de nombres de dominio de alto nivel
  •   
  • Resalte la parte más importante de un nombre de dominio en el usuario   interfaz
  •   
  • Ordenar con precisión las entradas del historial por sitio
  •   

Buscando en la lista , puedes ver que no es un problema trivial. Creo que una lista es la única forma correcta de lograr esto ...

Otros consejos

Publicsuffix.org parece el camino a seguir. Hay muchas implementaciones para analizar fácilmente el contenido del archivo de datos publicsuffix:

Como ya dijeron Adam y John, publicsuffix.org es el camino correcto. 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 todas, pero casi todas) "real" dominios 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

Aquí hay 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");
}

Como ya se dijo Lista de sufijos públicos es solo una forma de analizar el dominio correctamente. Para PHP, puede probar TLDExtract . Aquí está el código de muestra:

$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'

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

Para una biblioteca C (con generación de tabla de datos en Python), escribí http: //code.google.com/p/domain-registry-provider/ que es rápido y eficiente en el 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. Ver http://code.google.com/p/domain-registry- proveedor / wiki / DesignDoc para más detalles.

Para comprender mejor el código de generación de tablas (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, consulte: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/domain_registry/domain_registry.h

No está funcionando exactamente, pero tal vez podría obtener una respuesta útil al tratar de obtener el dominio pieza por pieza y verificar la respuesta, es decir, obtener ' 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.

A veces solo tienes que probarlo :)

Editar:

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

Usa el URIBuilder luego obtenga el atributo URIBUilder.host dividirlo en una matriz en ". " ahora tiene una matriz con el dominio dividido.

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

Acabo de escribir una biblioteca objc: https://github.com/kejinlu/KKDomain

Puede usar esta lib tld.js: API de JavaScript para trabajar con nombres de dominio complejos, subdominios y URI .

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

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

Usar cookies es complicado.

Si está buscando extraer subdominios y / o dominios de una lista arbitraria de URL, este script de Python puede ser útil. Sin embargo, ten cuidado, no es perfecto. Este es un problema difícil de resolver en general y es muy útil si tiene una lista blanca de dominios que espera.

  1. Obtenga dominios de nivel superior de publicsuffix.org
import requests

url = 'https://publicsuffix.org/list/public_suffix_list.dat'
page = requests.get(url)

domains = []
for line in page.text.splitlines():
    if line.startswith('//'):
        continue
    else:
        domain = line.strip()
        if domain:
            domains.append(domain)

domains = [d[2:] if d.startswith('*.') else d for d in domains]
print('found {} domains'.format(len(domains)))
  1. Crear expresiones regulares
import re

_regex = ''
for domain in domains:
    _regex += r'{}|'.format(domain.replace('.', '\.'))

subdomain_regex = r'/([^/]*)\.[^/.]+\.({})/.*

  1. Usar expresiones regulares en la lista de URL
FILE_NAME = ''   # put CSV file name here
URL_COLNAME = '' # put URL column name here

import pandas as pd

df = pd.read_csv(FILE_NAME)
urls = df[URL_COLNAME].astype(str) + '/' # note: adding / as a hack to help regex

df['sub_domain_extracted'] = urls.str.extract(pat=subdomain_regex, expand=True)[0]
df['domain_extracted'] = urls.str.extract(pat=domain_regex, expand=True)[0]

df.to_csv('extracted_domains.csv', index=False)
.format(_regex) domain_regex = r'([^/.]+\.({}))/.*
  1. Usar expresiones regulares en la lista de URL
<*>.format(_regex)
  1. Usar expresiones regulares en la lista de URL
<*>

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

El mayor problema es la lista de posibles sufijos. Hay mucho, después de todo.

Después de echar un vistazo rápido a la lista publicsuffix.org, parece que podría hacer una aproximación razonable eliminando los tres segmentos finales (" segmento " aquí significa una sección entre dos puntos) de los dominios donde está el segmento final dos caracteres de largo, en el supuesto de que sea 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 son dos caracteres, por lo tanto, elimine " domain.example " ;, dejando " www "

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

" reino unido " son dos caracteres (pero no "nosotros"), por lo tanto, elimine "dominio.co.uk", dejando "super.duper"

" nosotros " tiene dos caracteres y es "nosotros", más "wy" también tiene dos caracteres, así que 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 ahora, sigue siendo solo una aproximación razonable. No es completamente correcto, aunque sospecho que es lo más cercano posible sin hacer / obtener una lista real para usar como referencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top