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.uk
和 co.it
,它可以正确处理*** TLD,但会正确删除 .com
和 .co.uk
的 www
和 mail
子域
脚本开头的 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——提取没有子域的域名的主要内容,如果未能解决你的问题,请参考以下文章