繁体   English   中英

如何从 URL 中提取顶级域名 (TLD)

[英]How to extract top-level domain name (TLD) from URL

您将如何从 URL 中提取域名,不包括任何子域?

我最初的简单尝试是:

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

这适用于http://www.foo.com ,但不适用于http://www.foo.com.au 有没有一种方法可以在不使用有关有效 TLD(顶级域)或国家/地区代码(因为它们会更改)的特殊知识的情况下正确执行此操作。

谢谢

这是有人在看到这个问题后为解决这个问题而编写的一个很棒的 python 模块: https : //github.com/john-kurkowski/tldextract

该模块在由 Mozilla 志愿者维护的公共后缀列表中查找 TLD

引用:

另一方面, tldextract知道所有 gTLD [通用顶级域] 和 ccTLD [国家/地区代码顶级域] 根据公共后缀列表查找当前存在的域名 所以,给定一个 URL,它从它的域中知道它的子域,从它的国家代码中知道它的域。

不,没有“内在”方式知道(例如) zap.co.it是一个子域(因为意大利的注册商确实出售co.it等域)而zap.co.uk不是(因为英国的注册商不出售诸如co.uk域,而仅出售诸如zap.co.uk类的zap.co.uk )。

您只需要使用辅助表(或在线资源)来告诉您哪些 TLD 的行为与英国和澳大利亚的表现特别相似——没有办法通过只盯着字符串而没有这种额外的语义知识来判断这一点(当然它可以最终会改变,但如果你能找到一个好的在线资源,该资源也会相应地改变,希望!-)。

使用其他人在 Mozilla 网站上找到的有效 tlds 文件

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)

结果是:

abcde.co.uk

如果有人让我知道上面的哪些部分可以用更pythonic的方式重写,我将不胜感激。 例如,必须有更好的方法来迭代last_i_elements列表,但我想不出一个方法。 我也不知道ValueError是否是最好的选择。 评论?

使用 python tld

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

安装

pip install tld

从给定的 URL 中获取 TLD 名称作为字符串

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

联合王国

或没有协议

from tld import get_tld

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

联合王国

获取 TLD 作为对象

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=''
# )

从给定的 URL 中获取一级域名作为字符串

from tld import get_fld

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

在所有新的 get_tld 更新之前,我从错误中提取 tld。 当然这是糟糕的代码,但它有效。

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

这是我的处理方式:

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)

在 Python 中,我曾经使用tldextract直到它失败,网址如www.mybrand.sa.com解析为subdomain='order.mybrand', domain='sa', suffix='com' !!

所以最后,我决定写这个方法

重要说明:这仅适用于其中包含子域的 url。 这并不意味着取代更高级的库,如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:])}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM