【问题标题】:Python urlparse -- extract domain name without subdomainPython urlparse——提取没有子域的域名
【发布时间】:2013-01-02 14:22:18
【问题描述】:

需要一种使用 Python urlparse 从 url 中提取不带子域的域名的方法。

例如,我想从像"http://www.google.com" 这样的完整网址中提取"google.com"

我似乎与urlparse 最接近的是netloc 属性,但这包括子域,在本例中为www.google.com

我知道可以编写一些自定义字符串操作来将 www.google.com 转换为 google.com,但我想避免在此任务中手动进行字符串转换或正则表达式。 (原因是我对 url 形成规则不够熟悉,因此我有信心可以考虑编写自定义解析函数所需的每个边缘情况。)

或者,如果 urlparse 不能满足我的需求,有谁知道其他 Python url 解析库可以做到吗?

【问题讨论】:

  • 当您说 删除 www 时,是指所有子域,还是仅指那个特定的子域?
  • @Lattyware -- 好问题,抱歉我没有说得更清楚。我编辑了问题以反映答案。
  • 那么对于google.co.uk,你想摆脱google?!?
  • @Anony-Mousse,不,我想要来自 www.google.co.uk 的 google.co.uk。很抱歉,第一次措辞不是很清楚,我再次对其进行了编辑以使其更清晰。

标签: python parsing url urlparse


【解决方案1】:

对于域名操作,你也可以使用Dnspy(免责声明:这个库是我写的)

它有助于提取不同级别的域(和域标签),使用 Mozilla 公共后缀列表的新副本。

【讨论】:

  • 您应该添加免责声明。
  • @Sandy 添加了免责声明
【解决方案2】:

有多个 Python 模块将(曾经是 Mozilla)公共后缀列表封装在一个库中,其中一些要求输入是 URL。尽管该问题专门询问 URL 规范化,但我的要求是只处理域名,因此我提供了一个切题的答案。

publicsuffix2 相对于publicsuffixlistpublicsuffix 的相对优点尚不清楚,但它们似乎都提供了基本功能。

publicsuffix2:

>>> import publicsuffix  # sic
>>> publicsuffix.PublicSuffixList().get_public_suffix('www.google.co.uk')
u'google.co.uk'
  • 应该是publicsuffix 的更易于包装的分支。

公共后缀列表:

>>> import publicsuffixlist
>>> publicsuffixlist.PublicSuffixList().privatesuffix('www.google.co.uk')
'google.co.uk'
  • 宣传idna 支持,但我尚未测试。

公共后缀:

>>> import publicsuffix
>>> publicsuffix.PublicSuffixList(publicsuffix.fetch()).get_public_suffix('www.google.co.uk')
'google.co.uk'
  • 自行处理更新和缓存下载文件的要求有点复杂。

【讨论】:

    【解决方案3】:

    您可能想查看 tldextract,这是一个专为执行此类操作而设计的库。

    它使用公共后缀列表尝试根据已知 gTLD 进行适当的拆分,但请注意,这只是一个蛮力列表,没有什么特别之处,因此它可能会过时(尽管希望它经过精心策划不)。

    >>> import tldextract
    >>> tldextract.extract('http://forums.news.cnn.com/')
    ExtractResult(subdomain='forums.news', domain='cnn', suffix='com')
    

    所以在你的情况下:

    >>> extracted = tldextract.extract('http://www.google.com')
    >>> "{}.{}".format(extracted.domain, extracted.suffix)
    "google.com"
    

    【讨论】:

    • 不过看起来是一个很好的启发式方法。我认为很多时候,只是去除已知前缀(www. 等)会更有用。
    • @Anony-Mousse 很大程度上取决于用例。
    • ExtractResult(subdomain='my.first', domain='last', tld='name') - 这是您所期望的。
    • tldextract 拉入了所有requests,这似乎有点过分了。 tldextract.extract('www.google.co.uk') 给了我多个 SSL 警告 (!) 但最终成功了。
    • 我想提请注意tldextract 包的一个严重缺陷。没有验证。我将它用于一个小项目,我注意到 tldextract 并不关心字符串是什么。 >>> k = tldextract.extract('index.php?page=sign-varen') >>> k ExtractResult(subdomain='index', domain='php', suffix='')>>> k = tldextract.extract('step1_orderintro.html') >>> k ExtractResult(subdomain='step1_orderintro', domain='html', suffix='')
    【解决方案4】:
    from tld import get_tld
    from tld.utils import update_tld_names
    update_tld_names()
    
    result=get_tld('http://www.google.com')
    print 'https://'+result
    

    输入:http://www.google.com

    结果:google.com

    【讨论】:

    • 这似乎是@Andy 的回答的重复。
    【解决方案5】:

    这是一个更新,基于对更新答案的赏金请求

    首先使用tld 包。包装说明:

    从给定的 URL 中提取顶级域 (TLD)。顶级域名列表 名称取自 Mozilla http://mxr.mozilla.org/mozilla/source/netwerk/dns/src/effective_tld_names.dat?raw=1

    from tld import get_tld
    from tld.utils import update_tld_names
    update_tld_names()
    
    print get_tld("http://www.google.co.uk")
    print get_tld("http://zap.co.it")
    print get_tld("http://google.com")
    print get_tld("http://mail.google.com")
    print get_tld("http://mail.google.co.uk")
    print get_tld("http://google.co.uk")
    

    这个输出

    google.co.uk
    zap.co.it
    google.com
    google.com
    google.co.uk
    google.co.uk
    

    请注意,通过保留 co.ukco.it,它可以正确处理国家级 TLD,但会正确删除 .com.co.ukwwwmail 子域

    脚本开头的 update_tld_names() 调用用于将 tld 名称更新/同步到 Mozilla 的最新版本。

    【讨论】:

    • 有什么特别的理由推荐这个而不是tldextract 和/或publicsuffix
    • tld.get_tld('www.google.co.uk', fix_protocol=True) 对我来说失败,出现“url 格式的零长度字段名称”。
    • 不确定是否是版本问题,但在 python3.6 上,get_tld("http://mail.google.co.uk") 返回co.uk,类似。
    【解决方案6】:

    使用 tldexport 可以正常工作,但在解析 blogspot.com 子域时显然会出现问题并造成混乱。 如果您想继续使用该库,请确保实现 if 条件或其他内容以防止在子域中返回空字符串。

    【讨论】:

      【解决方案7】:

      这不是 URL 的标准分解

      您不能依赖www. 存在或可选。在很多情况下不会。

      因此,如果您确实想假设只有最后两个组件是相关的(这也不适用于英国,例如 www.google.co.uk),那么您可以执行 split('.')[-2:]

      或者,实际上更不容易出错,去掉 www. 前缀。

      但无论哪种方式您都不能假设www. 是可选的,因为它不会每次都有效!

      以下是域的常用后缀列表。您可以尝试保留后缀+一个组件。

      https://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1

      但是您打算如何处理例如first.last.name 域?假设所有具有相同姓氏的用户都是同一家公司?最初,您只能在那里获得三级域。到目前为止,您显然也可以达到第二级。所以对于.name 没有一般规则。

      【讨论】:

      • +1 指出没有实际的正确答案,并提供两个最佳启发式方法(使用或从其他地方获取)“有效 TLD”列表,然后选择模棱两可的,或使用“可丢弃前缀”列表并保留其他所有内容)。
      猜你喜欢
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      相关资源
      最近更新 更多