Como extrair o nome de domínio de nível superior (TLD) de URL
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
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
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'
Existem muitas, muitas TLD. Aqui está a lista:
http://data.iana.org/TLD/tlds alfa-by-domain.txt
Aqui está outra lista ??p>
http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
Aqui está outra lista ??p>
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:])}