55

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

例如,我想"google.com"从完整的 url中提取"http://www.google.com".

我能想到的最接近的urlparsenetloc属性,但它包括子域,在本例中为www.google.com.

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

或者,如果urlparse不能做我需要的,有没有人知道任何其他 Python url 解析库?

4

7 回答 7

75

您可能想查看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"
于 2013-01-18T19:38:35.500 回答
25

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

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

从给定的 URL 中提取顶级域 (TLD)。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请注意,它通过离开and正确处理国家级 TLD co.it,但正确删除了wwwand的mail子域.com.co.uk

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

于 2014-03-06T14:59:52.120 回答
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没有一般规则。

于 2013-01-18T19:36:27.747 回答
2

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

它使用 Mozilla 公共后缀列表的新副本帮助提取各个级别的域(和域标签)。

于 2014-02-24T21:33:02.060 回答
1

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

于 2013-08-18T19:37:10.803 回答
0
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

于 2015-01-21T09:57:14.247 回答
0

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

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

公共后缀2:

>>> 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'
  • 自己处理更新和缓存下载文件的要求有点复杂。
于 2017-03-29T10:56:05.710 回答