Pergunta

como você extrair o nome de domínio a partir de uma URL, excluindo todos os subdomínios?

Minha tentativa simplista inicial era:

'.'.join(urlparse.urlparse(url).netloc.split('.')[-2:])

Isso funciona para http://www.foo.com , mas não http://www.foo.com.au . Existe uma maneira de fazer isso corretamente sem o uso de conhecimento especial sobre TLDs válidos (Top Level Domains) ou códigos de países (porque eles mudam).

graças

Foi útil?

Solução

Não, não há nenhuma maneira "intrínseca" de saber que (por exemplo) zap.co.it é um subdomínio (por causa secretário da Itália FAZ domínios vender como co.it), enquanto zap.co.uk não é (porque registro do Reino Unido domínios não vende como co.uk, mas apenas como zap.co.uk).

Você apenas tem que usar uma tabela auxiliar (ou fonte on-line) para dizer-lhe que se comportam de TLD peculiarmente como o Reino Unido da e da Austrália - não há nenhuma maneira de adivinhar que a partir de apenas olhando para a seqüência sem tal conhecimento extra semântica (de É claro que pode mudar eventualmente, mas se você pode encontrar uma boa fonte on-line que fonte também vai mudar nesse sentido, espera-se -).

Outras dicas

Aqui está um grande módulo python alguém escreveu para resolver este problema depois de ver esta pergunta: https://github.com/john-kurkowski/tldextract

O módulo olha para cima TLDs na Public lista de sufixos , mantido pela voluntários Mozilla

Citação:

tldextract por outro lado sabe o que todos os gTLDs [ domínios genéricos de primeiro nível ] e ccTLDs [ Código do país Domínios de nível superior ] olhar como , observando-se os que vivem atualmente de acordo com a Sufixo Pública lista. Assim, dado um URL, ele conhece o seu subdomínio de seu domínio, e sua domínio de seu código de país.

Usando esse arquivo de tlds eficazes alguém encontradas no site da Mozilla :

from __future__ import with_statement
from urlparse import urlparse

# load tlds, ignore comments and empty lines:
with open("effective_tld_names.dat.txt") as tld_file:
    tlds = [line.strip() for line in tld_file if line[0] not in "/\n"]

def get_domain(url, tlds):
    url_elements = urlparse(url)[1].split('.')
    # url_elements = ["abcde","co","uk"]

    for i in range(-len(url_elements), 0):
        last_i_elements = url_elements[i:]
        #    i=-3: ["abcde","co","uk"]
        #    i=-2: ["co","uk"]
        #    i=-1: ["uk"] etc

        candidate = ".".join(last_i_elements) # abcde.co.uk, co.uk, uk
        wildcard_candidate = ".".join(["*"] + last_i_elements[1:]) # *.co.uk, *.uk, *
        exception_candidate = "!" + candidate

        # match tlds: 
        if (exception_candidate in tlds):
            return ".".join(url_elements[i:]) 
        if (candidate in tlds or wildcard_candidate in tlds):
            return ".".join(url_elements[i-1:])
            # returns "abcde.co.uk"

    raise ValueError("Domain not in global list of TLDs")

print get_domain("http://abcde.co.uk", tlds)

resulta em:

abcde.co.uk

eu apreciaria se alguém deixe-me saber quais bits do acima poderia ser reescrito de uma maneira mais Python. Por exemplo, deve haver uma maneira melhor de iteração sobre a lista last_i_elements, mas eu não conseguia pensar em um. Eu também não sei se ValueError é a melhor coisa para elevar. Comentários?

Usando python tld

https://pypi.python.org/pypi/tld

Instalar

pip install tld

Get o nome TLD como corda do URL dado

from tld import get_tld
print get_tld("http://www.google.co.uk") 

co.uk

ou sem protocolo

from tld import get_tld

get_tld("www.google.co.uk", fix_protocol=True)

co.uk

Obter o TLD como um objeto

from tld import get_tld

res = get_tld("http://some.subdomain.google.co.uk", as_object=True)

res
# 'co.uk'

res.subdomain
# 'some.subdomain'

res.domain
# 'google'

res.tld
# 'co.uk'

res.fld
# 'google.co.uk'

res.parsed_url
# SplitResult(
#     scheme='http',
#     netloc='some.subdomain.google.co.uk',
#     path='',
#     query='',
#     fragment=''
# )

Get o primeiro nome de domínio de nível como corda do URL dado

from tld import get_fld

get_fld("http://www.google.co.uk")
# 'google.co.uk'

Aqui está como eu lidar com isso:

if not url.startswith('http'):
    url = 'http://'+url
website = urlparse.urlparse(url)[1]
domain = ('.').join(website.split('.')[-2:])
match = re.search(r'((www\.)?([A-Z0-9.-]+\.[A-Z]{2,4}))', domain, re.I)
if not match:
    sys.exit(2)
elif not match.group(0):
    sys.exit(2)

Até get_tld é atualizado para todos os novos, eu puxo o TLD do erro. Claro que é um código ruim, mas ele funciona.

def get_tld():
  try:
    return get_tld(self.content_url)
  except Exception, e:
    re_domain = re.compile("Domain ([^ ]+) didn't match any existing TLD name!");
    matchObj = re_domain.findall(str(e))
    if matchObj:
      for m in matchObj:
        return m
    raise e

Em Python Eu costumava usar o tldextract até que falhou com uma URL como www.mybrand.sa.com analisá-lo como subdomain='order.mybrand', domain='sa', suffix='com' !!

Então, finalmente, eu decidi escrever este método

NOTA IMPORTANTE: isso só funciona com URLs que tenham um subdomínio neles. Isto não se destina a substituir as bibliotecas mais avançadas como tldextract

def urlextract(url):
  url_split=url.split(".")
  if len(url_split) <= 2:
      raise Exception("Full url required with subdomain:",url)
  return {'subdomain': url_split[0], 'domain': url_split[1], 'suffix': ".".join(url_split[2:])}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top