web-dev-qa-db-ja.com

URLからトップレベルドメイン名(TLD)を抽出する方法

サブドメインを除外して、URLからどのようにドメイン名を抽出しますか?

私の最初の単純な試みは:

'.'.join(urlparse.urlparse(url).netloc.split('.')[-2:])

これは http://www.foo.com で機能しますが、 http://www.foo.com.a では機能しません。有効なTLD(トップレベルドメイン)または国コード(変更されているため)に関する特別な知識を使用せずに、これを適切に行う方法はありますか。

ありがとう

49
hoju

いいえ、(たとえば)zap.co.itがサブドメイン(イタリアのレジストラはco.itなどのドメインを販売しているため)であり、zap.co.ukis n't(UKのレジストラはco.ukなどのドメインを販売していないが、zap.co.ukのみを販売しているため)。

補助テーブル(またはオンラインソース)を使用するだけで、どのTLDが英国やオーストラリアのように振る舞うかを知る必要があります-このような余分なセマンティックな知識なしに文字列をじっと見つめることからそれを推測する方法はありません(もちろんできます)最終的に変更されますが、適切なオンラインソースを見つけることができれば、そのソースもそれに応じて変更されます。

43
Alex Martelli

この質問を見た後に誰かがこの問題を解決するために書いた素晴らしいモジュールpythonモジュール: https://github.com/john-kurkowski/tldextract

このモジュールは、Mozillaボランティアによって管理されている Public Suffix List でTLDを検索します

見積もり:

一方、tldextractは、すべてのgTLD [Generic Top-Level Domains]およびccTLD [国コードトップレベルドメイン] Public Suffix List に従って現在生きているドメインを検索すると、次のようになります。そのため、URLを指定すると、そのドメインからそのサブドメインを、国コードからそのドメインを認識します。

47
Acorn

有効な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がレイズするのに最適かどうかもわかりません。コメント?

42
Markus

python tldを使用

https://pypi.python.org/pypi/tld

インストール

pip install tld

指定されたURLから文字列として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

TLDをオブジェクトとして取得します

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=''
# )

指定されたURLから文字列として第1レベルのドメイン名を取得します

from tld import get_fld

get_fld("http://www.google.co.uk")
# 'google.co.uk'
26

多くのTLDがあります。リストは次のとおりです。

http://data.iana.org/TLD/tlds-alpha-by-domain.txt

ここに別のリストがあります

http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains

ここに別のリストがあります

http://www.iana.org/domains/root/db/

2
S.Lott

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
0
Russ Savage

以下がその処理方法です。

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)
0
Ryan Buckley