Python urlparse——提取没有子域的域名

Posted

技术标签:

【中文标题】Python urlparse——提取没有子域的域名【英文标题】:Python urlparse -- extract domain name without subdomain 【发布时间】: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 时,是指所有子域,还是仅指那个特定的子域? 相关:***.com/questions/1066933/… @Lattyware -- 好问题,抱歉我没有说得更清楚。我编辑了问题以反映答案。 那么对于google.co.uk,你想摆脱google?!? @Anony-Mousse,不,我想要来自 www.google.co.uk 的 google.co.uk。很抱歉,第一次措辞不是很清楚,我再次对其进行了编辑以使其更清晰。 【参考方案1】:

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

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

【讨论】:

您应该添加免责声明。 @Sandy 添加了免责声明【参考方案2】:

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

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

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”列表,然后选择模棱两可的,或使用“可丢弃前缀”列表并保留其他所有内容)。

以上是关于Python urlparse——提取没有子域的域名的主要内容,如果未能解决你的问题,请参考以下文章

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

子域的域设置 cookie

如何将通配符子域重定向到我的域

不仅从不同的子域,而是从不同的域提供图像(安全)是不是符合 PCI 标准?

如何将网站从子域转移到主域

我可以在不使用 Route 53 的情况下将我的域和子域指向 AWS 托管吗?