Python正则失效,无法匹配出任何结果

需求

一个方法,可以匹配出任何域名的 顶级域名 以及域名层级。

测试用例
输入 www.baidu.com 返回 [baidu.com,1]
输入 baidu.com 返回 [baidu.com,1]
输入 google.com.cn 返回 [google.com.cn,1]
输入 www.test.baidu.com.kkk.cooococo.google.com.jp 返回 [google.com.jp, 7]

代码

匹配不到任何东西

def parse_host(hostname) :
    """获取顶级域名
    """
    hostname = hostname.lower()
    m = re.match('[a-zA-Z0-9-]+\.(((?:(com|org|net)\.)(cn|jp|kr|fr|tw|hk))|(com|cn|net|org|fr|la|biz|cc|tv|co\.jp|name|me|us|de|info|uk))$', hostname)
    if m is not None :
        tophost = m.group(0)
        if tophost == hostname or 'www.' + tophost == hostname :
            hostlevel = 1
        else :
            hostlevel = hostname.count('.') - tophost.count('.') + 1
    else :
        hostlevel = 0
        tophost = ""
    return [tophost, hostlevel]
阅读 3.8k
1 个回答

作者:顾轶灵
链接:https://www.zhihu.com/questio...
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

用正则表达式精准抽取「主域名」是做不到的。

举个例子,给你 http://www.sina.com.cn 这样的 URL,你觉得主域名是什么呢?是 sina.com.cn 还是 com.cn 呢?

从常识来说,我们所希望得到的主域名,应该是能够清晰区分网站主体的域名后缀,比如上面的例子,就是 http://sina.com.cn。那域名中的哪段内容才能区分网站主体呢?想一下就可以得出,是把整个域名从右往左分段,找到第一个「非公用」的部分。

首先,域名从右往左第一段是顶级域名(TLD),其中又分为通用顶级域名(gTLDs,如 .com、.edu、.org 等)和国家地区代码顶级域名(ccTLDs,如 .cn、.uk、.hk 等)。ICANN 统一管理 gTLDs,并将 ccTLDs 下放给各种域名注册机构管理,例如国家地区顶级域名就交由不同国家地区来管理。中国大陆的域名管理机构为著名的 CNNIC。我们再以 .cn 域名为例,下设一些预定义的「类别域名」如 .http://com.cn、.http://org.cn、.http://edu.cn 以及「行政区域名」如 .http://sh.cn、.http://bj.cn,并且同时开放 .cn 域名的注册。这意味着,我注册一个叫 test 的域名,既可以是 http://test.com.cn 也可以是 http://test.cn,也就是说,那些域名的「公用部分」长度是不确定的。那么如果给我一个 URL 我是没法以一个固定的方式来做截取的,而是必须知道这个 URL 的域名中哪个最长的后缀已经被某个域名管理机构预定义为公用的域名,然后剔除掉这部分才能找到第一个非公用的部分。

幸好,有 Public Suffix List 这样的项目,你可以利用它提供的列表,来提取需要的「主域名」。目前的数据见:http://mxr.mozilla.org/mozill...。另外,你可以看看这个列表:Learn more about the Public Suffix List,看看都有谁在使用和维护这份数据,以及他们都用来干嘛,比如:
Firefox 用来做浏览器地址栏的反钓鱼(高亮显示正确的「主域名」)

Firefox 和 Chrome 都用其来进行 Cookie 相关的域名检测
Chrome 用来判断用户在地址栏输入的是否是一个域名

从这个页面你也可以看到,你用 JavaScript 的话,可以直接使用 tld.js 这个项目来提取主域名。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进