comment extrairez-vous le nom de domaine d'une URL, à l'exclusion de tout sous-domaine?
Ma tentative simpliste initiale était:
'.'.join(urlparse.urlparse(url).netloc.split('.')[-2:])
Cela fonctionne pour http://www.foo.com , mais pas http://www.foo.com.a . Existe-t-il un moyen de le faire correctement sans utiliser de connaissances particulières sur les TLD (domaines de premier niveau) ou les codes de pays valides (car ils changent).
merci
Non, il n'y a aucun moyen "intrinsèque" de savoir que (par exemple) zap.co.it
est un sous-domaine (car le bureau d'enregistrement italien vend des domaines tels que co.it
) tandis que zap.co.uk
n'est pas (car le bureau d'enregistrement britannique NE VEND PAS de domaines tels que co.uk
, mais seulement comme zap.co.uk
).
Vous n'aurez qu'à utiliser une table auxiliaire (ou une source en ligne) pour vous dire quels TLD se comportent particulièrement comme ceux du Royaume-Uni et de l'Australie - il n'y a aucun moyen de deviner cela en regardant simplement la chaîne sans une telle connaissance sémantique supplémentaire (bien sûr, cela peut changer éventuellement, mais si vous pouvez trouver une bonne source en ligne, cette source changera également en conséquence, on espère! -).
Voici un excellent module python que quelqu'un a écrit pour résoudre ce problème après avoir vu cette question: https://github.com/john-kurkowski/tldextract
Le module recherche les TLD dans la Public Suffix List , maintenue par les bénévoles de Mozilla
Citation:
tldextract
d'autre part sait ce que tous les gTLD [ domaines génériques de premier niveau ] et ccTLD [ Les domaines de premier niveau de code de pays ] ressemblent en recherchant ceux actuellement en vigueur selon la Liste des suffixes publics . Ainsi, étant donné une URL, il connaît son sous-domaine à partir de son domaine et son domaine à partir de son code pays.
Utiliser ce fichier de tlds efficaces qui quelqu'un d'autre trouvé sur le site Web de 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)
résulte en:
abcde.co.uk
J'apprécierais que quelqu'un me fasse savoir quels morceaux de ce qui précède pourraient être réécrits d'une manière plus pythonique. Par exemple, il doit y avoir une meilleure façon d'itérer sur le last_i_elements
liste, mais je n'y ai pas pensé. Je ne sais pas non plus si ValueError
est la meilleure chose à faire. Commentaires?
Utilisation de python tld
https://pypi.python.org/pypi/tld
pip install tld
from tld import get_tld
print get_tld("http://www.google.co.uk")
co.uk
ou sans protocole
from tld import get_tld
get_tld("www.google.co.uk", fix_protocol=True)
co.uk
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=''
# )
from tld import get_fld
get_fld("http://www.google.co.uk")
# 'google.co.uk'
Il existe de très nombreux TLD. Voici la liste:
http://data.iana.org/TLD/tlds-alpha-by-domain.txt
Voici une autre liste
http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
Voici une autre liste
Jusqu'à ce que get_tld soit mis à jour pour tous les nouveaux, je tire le tld de l'erreur. Bien sûr, c'est un mauvais code, mais cela fonctionne.
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
Voici comment je le gère:
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)