サブドメインを除外して、URLからどのようにドメイン名を抽出しますか?
私の最初の単純な試みは:
'.'.join(urlparse.urlparse(url).netloc.split('.')[-2:])
これは http://www.foo.com で機能しますが、 http://www.foo.com.a では機能しません。有効なTLD(トップレベルドメイン)または国コード(変更されているため)に関する特別な知識を使用せずに、これを適切に行う方法はありますか。
ありがとう
いいえ、(たとえば)zap.co.it
がサブドメイン(イタリアのレジストラはco.it
などのドメインを販売しているため)であり、zap.co.uk
is n't(UKのレジストラはco.uk
などのドメインを販売していないが、zap.co.uk
のみを販売しているため)。
補助テーブル(またはオンラインソース)を使用するだけで、どのTLDが英国やオーストラリアのように振る舞うかを知る必要があります-このような余分なセマンティックな知識なしに文字列をじっと見つめることからそれを推測する方法はありません(もちろんできます)最終的に変更されますが、適切なオンラインソースを見つけることができれば、そのソースもそれに応じて変更されます。
この質問を見た後に誰かがこの問題を解決するために書いた素晴らしいモジュールpythonモジュール: https://github.com/john-kurkowski/tldextract
このモジュールは、Mozillaボランティアによって管理されている Public Suffix List でTLDを検索します
見積もり:
一方、
tldextract
は、すべてのgTLD [Generic Top-Level Domains]およびccTLD [国コードトップレベルドメイン] Public Suffix List に従って現在生きているドメインを検索すると、次のようになります。そのため、URLを指定すると、そのドメインからそのサブドメインを、国コードからそのドメインを認識します。
有効なtldのこのファイル which 他の誰か をMozillaのWebサイトで見つけました:
from __future__ import with_statement
from urlparse import urlparse
# load tlds, ignore comments and empty lines:
with open("effective_tld_names.dat.txt") as tld_file:
tlds = [line.strip() for line in tld_file if line[0] not in "/\n"]
def get_domain(url, tlds):
url_elements = urlparse(url)[1].split('.')
# url_elements = ["abcde","co","uk"]
for i in range(-len(url_elements), 0):
last_i_elements = url_elements[i:]
# i=-3: ["abcde","co","uk"]
# i=-2: ["co","uk"]
# i=-1: ["uk"] etc
candidate = ".".join(last_i_elements) # abcde.co.uk, co.uk, uk
wildcard_candidate = ".".join(["*"] + last_i_elements[1:]) # *.co.uk, *.uk, *
exception_candidate = "!" + candidate
# match tlds:
if (exception_candidate in tlds):
return ".".join(url_elements[i:])
if (candidate in tlds or wildcard_candidate in tlds):
return ".".join(url_elements[i-1:])
# returns "abcde.co.uk"
raise ValueError("Domain not in global list of TLDs")
print get_domain("http://abcde.co.uk", tlds)
結果:
abcde.co.uk
上記のどの部分がよりPython的な方法で書き換えられるかを誰かに教えていただければ幸いです。たとえば、last_i_elements
リストを反復処理するより良い方法が必要ですが、それを考えることはできませんでした。 ValueError
がレイズするのに最適かどうかもわかりません。コメント?
python tld
を使用
https://pypi.python.org/pypi/tld
pip install tld
from tld import get_tld
print get_tld("http://www.google.co.uk")
co.uk
またはプロトコルなし
from tld import get_tld
get_tld("www.google.co.uk", fix_protocol=True)
co.uk
from tld import get_tld
res = get_tld("http://some.subdomain.google.co.uk", as_object=True)
res
# 'co.uk'
res.subdomain
# 'some.subdomain'
res.domain
# 'google'
res.tld
# 'co.uk'
res.fld
# 'google.co.uk'
res.parsed_url
# SplitResult(
# scheme='http',
# netloc='some.subdomain.google.co.uk',
# path='',
# query='',
# fragment=''
# )
from tld import get_fld
get_fld("http://www.google.co.uk")
# 'google.co.uk'
多くのTLDがあります。リストは次のとおりです。
http://data.iana.org/TLD/tlds-alpha-by-domain.txt
ここに別のリストがあります
http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
ここに別のリストがあります
Get_tldがすべての新しいものに対して更新されるまで、エラーからtldを取得します。確かにそれは悪いコードですが、動作します。
def get_tld():
try:
return get_tld(self.content_url)
except Exception, e:
re_domain = re.compile("Domain ([^ ]+) didn't match any existing TLD name!");
matchObj = re_domain.findall(str(e))
if matchObj:
for m in matchObj:
return m
raise e
以下がその処理方法です。
if not url.startswith('http'):
url = 'http://'+url
website = urlparse.urlparse(url)[1]
domain = ('.').join(website.split('.')[-2:])
match = re.search(r'((www\.)?([A-Z0-9.-]+\.[A-Z]{2,4}))', domain, re.I)
if not match:
sys.exit(2)
Elif not match.group(0):
sys.exit(2)