URLからサブドメインを取得する


100

URLからサブドメインを取得することは、最初は簡単に聞こえます。

http://www.domain.example

最初の期間をスキャンし、「http://」の後に来たものを返します...

その後、あなたは覚えています

http://super.duper.domain.example

ああ。では、最後のピリオドを見つけて、一言戻ってすべてを手に入れてください。

その後、あなたは覚えています

http://super.duper.domain.co.uk

そして、あなたはスクエアワンに戻っています。すべてのTLDのリストを保存する以外に、素晴らしいアイデアはありますか?


この質問はすでにここで質問されています:URLの一部を取得編集:同様の質問がここで質問されました:)
jb。

あなたが何をしたいのか明確にするカム?URLの「公式」ドメイン部分(つまりdomain.co.uk)の後ろにいるようですが、その前に表示されているDNSラベルの数に関係はありませんか?
アルニタク

同じ質問ではないと思います-これは、文字列を見るだけでは解決できないドメイン名の管理カットについての詳細のようです
Alnitak

同意する。最終目標が何であるかについてさらに詳しく説明します。
BuddyJoe 2008年

この回答を参照してください:stackoverflow.com/a/39307593/530553
Ehsan Chavoshi

回答:


73

すべてのTLDのリストを保存する以外に、素晴らしいアイデアはありますか?

いいえ。各TLDは、サブドメイン、第2レベルドメインなどとして数えられるもので異なるためです。

トップレベルドメイン、セカンドレベルドメイン、およびサブドメインがあることに注意してください。技術的には、TLDを除くすべてがサブドメインです。

domain.com.ukの例では、「domain」はサブドメイン、「com」は第2レベルドメイン、「uk」はTLDです。

そのため、質問は最初の面白さよりも複雑であり、各TLDの管理方法に依存します。特定のパーティション化を含むすべてのTLDのデータベース、および第2レベルドメインとサブドメインとして数えられるものが必要です。ただし、TLDが多すぎないので、リストは合理的に管理できますが、そのすべての情報を収集することは簡単ではありません。利用可能なそのようなリストがすでにあるかもしれません。

以下のように見えるhttp://publicsuffix.org/は、検索に適したリストにそのようなリストのすべての共通のサフィックス(.COM、.co.uk、等)です。それでも簡単に解析することはできませんが、少なくともリストを維持する必要はありません。

「パブリックサフィックス」とは、インターネットユーザーが名前を直接登録できるものです。パブリックサフィックスの例としては、「。com」、「。co.uk」、「pvt.k12.wy.us」などがあります。パブリックサフィックスリストは、すべての既知のパブリックサフィックスのリストです。

Public Suffix Listは、Mozilla Foundationの主導によるものです。任意のソフトウェアで使用できますが、元々はブラウザメーカーのニーズを満たすために作成されました。たとえば、ブラウザで次のことができます。

  • 高レベルのドメイン名サフィックスにプライバシーを侵害する「supercookie」を設定しないでください。
  • ユーザーインターフェイスでドメイン名の最も重要な部分を強調表示する
  • サイトごとに履歴エントリを正確にソート

リストを見ると、それはささいな問題ではないことがわかります。リストはこれを達成する唯一の正しい方法だと思います...


Mozillaには、このサービスを使用するコードがあります。元のCookie仕様がTLDをCookieを信頼するようにリンクしていたため、プロジェクトは分離されましたが、機能しませんでした。「Cookie Monster」のバグが最初の問題であり、アーキテクチャが修正または交換されることはありませんでした。
2008年

これを解決するための推奨言語はリストされていませんが、このリストをC#コードで使用するオープンソースプロジェクトがあります:code.google.com/p/domainname-parser
Dan Esparza

ドメインが「パブリックサフィックス」であるかどうかにかかわらず、DNSプロトコル自体を介して、おそらくEDNSフラグを介して、ドメインを実際に使用できるようにする必要があります。その場合、所有者が設定でき、個別のリストを維持する必要はありません。
Pieter Ennes 2013

@PieterEnnes EDNSは「トランスポート関連」フラグ用であり、コンテンツ関連のメタデータには使用できません。この情報はDNS自体に配置するのが最適であることには同意します。ISTRバンクーバーで開催されるIETFでこれを議論するための「BoFセッション」の計画があります。
Alnitak 2013年

26

Adamが言うように、それは簡単ではありません、そして現在唯一の実用的な方法はリストを使うことです。

それでも例外があります。たとえば、.ukそのレベルですぐに有効であり.co.uk、にないドメインが少数あるため、それらを例外として追加する必要があります。

これは現在、主流のブラウザーがこれを行う方法です-がにexample.co.ukCookieを設定できないことを確認する必要があります.co.uk下にある他のWebサイトに送信される.co.ukます。

良いニュースは、http://publicsuffix.org/で利用可能なリストがすでにあることです。

IETFには、TLDがドメイン構造がどのように見えるかを宣言できるように、ある種の標準を作成する作業もいくつかあります。これは.uk.com、パブリックサフィックスであるかのように操作され.comますが、レジストリでは販売されていないため、少し複雑です。


1
たぶん、IETFはURLを消滅させるよりもよく知っているはずです。ドラフト(2012年9月に最終更新)は、こちらから入手できます:tools.ietf.org/html/draft-pettersen-subtld-structure
IMSoP

この件に関するIETFワーキンググループ(DBOUND)は終了しました。
Patrick Mevzek 2017年

これを書いたので、.ukドメインレジストリは第2レベルで直接登録を許可することに注意してください。これはPSLにも反映されます。
Alnitak 2018

22

Publicsuffix.orgがその方法のようです。publicsuffixデータファイルファイルの内容を簡単に解析するための実装は数多くあります。


2
しかし、それは単に解析の問題ではないことを忘れないでください!Publicsuffix.orgのこのリストは非公式なプロジェクトであり、不完全です(たとえば、eu.orgが欠落している)。TLDのポリシーを自動的に反映しておらず、いつでもメンテナンスされなくなる可能性があります。
bortzmeyer 09年


7
publicsuffix.orgのリストは、Mozillaがしている他の何よりも「非公式」ではありません。Mozilla、Opera、Chromeがそれを使用していることを考えると、メンテナンスされなくなることはほとんどありません。不完全であることに関しては、eu.orgのようなドメインの任意のオペレーターが、必要に応じて包含を申請でき、そうすることの結果を理解しています。ドメインを追加する場合は、所有者に申請してください。はい、それは自動的にTLDポリシーを反映しませんが、何も反映しません-その情報のプログラム的なソースはありません。
Gervase Markham

dagger / android:okhttpはtopPrivateDomain
bladerunnerを

9

アダムとジョンのpublicsuffix.orgですでに述べたようにように、が正しい方法です。ただし、何らかの理由でこのアプローチを使用できない場合は、すべてのドメインの99%で機能するという仮定に基づくヒューリスティックを次に示します。

「すべて」ではなく「ほぼすべて」の「実際の」ドメインをサブドメインおよびTLDから区別する1つのプロパティがあり、それがDNSのMXレコードです。これを検索するアルゴリズムを作成できます。ホスト名の部分を1つずつ削除し、MXレコードが見つかるまでDNSにクエリを実行します。例:

super.duper.domain.co.uk => no MX record, proceed
duper.domain.co.uk       => no MX record, proceed
domain.co.uk             => MX record found! assume that's the domain

これがphpの例です:

function getDomainWithMX($url) {
    //parse hostname from URL 
    //http://www.example.co.uk/index.php => www.example.co.uk
    $urlParts = parse_url($url);
    if ($urlParts === false || empty($urlParts["host"])) 
        throw new InvalidArgumentException("Malformed URL");

    //find first partial name with MX record
    $hostnameParts = explode(".", $urlParts["host"]);
    do {
        $hostname = implode(".", $hostnameParts);
        if (checkdnsrr($hostname, "MX")) return $hostname;
    } while (array_shift($hostnameParts) !== null);

    throw new DomainException("No MX record found");
}

IETFもここで提案していることですか?
Ellie Kesselman、2016年

1
publicsuffix.orgでさえ(6番目の段落を参照)、これを行う適切な方法は、回答で述べたように、DNSを介することであると述べています!
Ellie Kesselman 2016年

1
ただし、MXレコードがなくても完全にドメインを持つことができます。そして、そのアルゴリズムはワイルドカードレコードによってだまされます。そして反対側には、MXレコードを持つTLDがあります(.aiまたは.axいくつか例を挙げると)。
Patrick Mevzek

@patrick:私は完全に同意します。冒頭で述べたように、このアルゴリズムは完全なものではありません。驚くほどうまくいくのはヒューリスティックだけです。
フランソワブルジョワ

2

すでに述べたように、パブリックサフィックスリストはドメインを正しく解析するための1つの方法にすぎません。PHPの場合は、TLDExtractを試すことができます。これがサンプルコードです:

$extract = new LayerShifter\TLDExtract\Extract();

$result = $extract->parse('super.duper.domain.co.uk');
$result->getSubdomain(); // will return (string) 'super.duper'
$result->getSubdomains(); // will return (array) ['super', 'duper']
$result->getHostname(); // will return (string) 'domain'
$result->getSuffix(); // will return (string) 'co.uk'

1

publicsuffix.orgからの情報に基づいて、clojureでこのためのプログラムを書いただけです。

https://github.com/isaksky/url_dom

例えば:

(parse "sub1.sub2.domain.co.uk") 
;=> {:public-suffix "co.uk", :domain "domain.co.uk", :rule-used "*.uk"}

1

Cライブラリ(Pythonでのデータテーブル生成を使用)の場合、http://code.google.com/p/domain-registry-provider/を作成しました。

ライブラリは、データテーブルに〜30kB、Cコードに〜10kBを使用します。テーブルはコンパイル時に作成されるため、起動時のオーバーヘッドはありません。詳細については、http://code.google.com/p/domain-registry-provider/wiki/DesignDocを参照してください。

テーブル生成コード(Python)をよりよく理解するには、ここから始めてください:http : //code.google.com/p/domain-registry-provider/source/browse/trunk/src/registry_tables_generator/registry_tables_generator.py

C APIの理解を深めるには、http//code.google.com/p/domain-registry-provider/source/browse/trunk/src/domain_registry/domain_registry.hをご覧ください。


1
publicsuffix.orgリストに対してもチェックされますが、独自のリストを持つC / C ++ライブラリもあります。これはlibtldと呼ばれ、UnixおよびMS-Windows snapwebsites.org/project/libtldで
Alexis Wilke

0

正確に機能しているわけではありませんが、ドメインを1つずつフェッチして応答を確認することで、有用な回答が得られる可能性があります。つまり、「http:// uk」、次に「http://co.uk」をフェッチします。 、次に「http://domain.co.uk」。エラー以外の応答を受け取った場合、ドメインがあり、残りはサブドメインです。

時々あなたはそれを試さなければならない :)

編集:

Tom Leysはコメントで指摘しているように、一部のドメインはwwwサブドメインにのみ設定されているため、上記のテストでは不正解になります。いい視点ね!たぶん、最善のアプローチは、「http:// www」と「http://」で各部分をチェックし、ヒットをドメイン名のそのセクションのヒットとしてカウントすることでしょうか?「web.domain.com」などの「代替」の配置がまだ不足していますが、私はしばらくの間それらのいずれにも遭遇していません:)


www.x.comが指定する場合でも、x.comがポート80でWebサーバーを指定する保証はありません。この場合、wwwは有効なサブドメインです。おそらく、自動化されたwhoisが役立ちます。
Tom Leys

いい視点ね!whoisはそれをクリアしますが、どのwhoisサーバーを使用するかについてのリストを維持することは、どのtld / 2ndレベルでエッジケースの同じ問題を解決することを意味します。
jTresidder 2008年

すべてのドメインでHTTPサーバーが実行されていると想定している
Francois Bourgeois

そのままでは機能しますが.DK、他の一部では機能しませんhttp://dk/。この種のヒューリスティックは、進むべき道ではありません...
Patrick Mevzek

0

URIBuilderを使用してから、URIBUilder.host属性を取得して、 "。"上の配列に分割します。これで、ドメインが分割された配列ができました。


0
echo tld('http://www.example.co.uk/test?123'); // co.uk

/**
 * http://publicsuffix.org/
 * http://www.alandix.com/blog/code/public-suffix/
 * http://tobyinkster.co.uk/blog/2007/07/19/php-domain-class/
 */
function tld($url_or_domain = null)
{
    $domain = $url_or_domain ?: $_SERVER['HTTP_HOST'];
    preg_match('/^[a-z]+:\/\//i', $domain) and 
        $domain = parse_url($domain, PHP_URL_HOST);
    $domain = mb_strtolower($domain, 'UTF-8');
    if (strpos($domain, '.') === false) return null;

    $url = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';

    if (($rules = file($url)) !== false)
    {
        $rules = array_filter(array_map('trim', $rules));
        array_walk($rules, function($v, $k) use(&$rules) { 
            if (strpos($v, '//') !== false) unset($rules[$k]);
        });

        $segments = '';
        foreach (array_reverse(explode('.', $domain)) as $s)
        {
            $wildcard = rtrim('*.'.$segments, '.');
            $segments = rtrim($s.'.'.$segments, '.');

            if (in_array('!'.$segments, $rules))
            {
                $tld = substr($wildcard, 2);
                break;
            }
            elseif (in_array($wildcard, $rules) or 
                    in_array($segments, $rules))
            {
                $tld = $segments;
            }
        }

        if (isset($tld)) return $tld;
    }

    return false;
}


0

このlib tld.js:JavaScript APIを使用して、複雑なドメイン名、サブドメイン、およびURIを操作できます。

tldjs.getDomain('mail.google.co.uk');
// -> 'google.co.uk'

ブラウザでルートドメインを取得している場合。このlib AngusFu / browser-root-domainを使用できます

var KEY = '__rT_dM__' + (+new Date());
var R = new RegExp('(^|;)\\s*' + KEY + '=1');
var Y1970 = (new Date(0)).toUTCString();

module.exports = function getRootDomain() {
  var domain = document.domain || location.hostname;
  var list = domain.split('.');
  var len = list.length;
  var temp = '';
  var temp2 = '';

  while (len--) {
    temp = list.slice(len).join('.');
    temp2 = KEY + '=1;domain=.' + temp;

    // try to set cookie
    document.cookie = temp2;

    if (R.test(document.cookie)) {
      // clear
      document.cookie = temp2 + ';expires=' + Y1970;
      return temp;
    }
  }
};

クッキーの使用は注意が必要です。


0

URLの任意のリストからサブドメインやドメインを抽出する場合は、このpythonスクリプトが役立つことがあります。注意してください、それは完璧ではありません。これは一般に解決するのが難しい問題であり、期待しているドメインのホワイトリストがある場合は非常に役立ちます。

  1. publicsuffix.orgからトップレベルドメインを取得する
インポート要求

url = 'https://publicsuffix.org/list/public_suffix_list.dat'
ページ= requests.get(url)

ドメイン= []
page.text.splitlines()の行の場合:
    if line.startswith( '//'):
        継続する
    そうしないと:
        ドメイン= line.strip()
        ドメインの場合:
            domains.append(domain)

ドメイン= [d [2:] if d.startswith( '*。')else d for domain in d]
print( 'found {} domains'.format(len(domains)))
  1. 正規表現を作成する
インポート再

_regex = ''
ドメイン内のドメインの場合:
    _regex + = r '{} |' .format(domain.replace( '。'、 '\。'))

subdomain_regex = r '/([^/]*)\.[^/.]+\.({})/.*$'。format(_regex)
domain_regex = r '([^ /。] + \。({}))/.*$'。format(_regex)
  1. URLのリストで正規表現を使用する
FILE_NAME = ''#CSVファイル名をここに入力
URL_COLNAME = ''#ここにURL列名を入力

パンダをpdとしてインポート

df = pd.read_csv(FILE_NAME)
urls = df [URL_COLNAME] .astype(str)+ '/'#注:/を正規表現に役立つハックとして追加

df ['sub_domain_extracted'] = urls.str.extract(pat = subdomain_regex、expand = True)[0]
df ['domain_extracted'] = urls.str.extract(pat = domain_regex、expand = True)[0]

df.to_csv( 'extracted_domains.csv'、index = False)


-3

publicsuffix.orgリストをざっと見たところ、最後のセグメントが2文字の長さのドメインから最後の3つのセグメント(ここでは「セグメント」は2つのドットの間のセクションを意味する)を削除することで、妥当な概算ができるようです。国コードであり、さらに細分化されることを想定しています。最後のセグメントが「us」で、最後から2番目のセグメントも2文字の場合、最後の4つのセグメントを削除します。その他の場合はすべて、最後の2つのセグメントを削除します。例えば:

「example」は2文字ではないため、「domain.example」を削除して、「www」を残します

「example」は2文字ではないため、「domain.example」を削除し、「super.duper」を残します

「uk」は2文字(「us」は除く)なので、「domain.co.uk」を削除して、「super.duper」を残します

「us」は2文字で「us」であり、さらに「wy」も2文字なので、「pvt.k12.wy.us」を削除して「foo」を残します。

これは、これまでに応答で見たすべての例で機能しますが、妥当な概算にすぎないことに注意してください。完全に正しいわけではありませんが、参照に使用する実際のリストを作成/取得しなくても、あなたが得る可能性が高いと思われます。


3
失敗するケースはたくさんあります。これは、ブラウザが試行して使用するアルゴリズムの一種です。それを行わないでください。PSLを使用してください-PSLは機能し、あなたを助けるライブラリがあります。
Gervase Markham

また、gTLDを「セグメント化」することを禁止するものは何もありません。これは、.NAMEたとえばfirstname.lastname.nameドメイン名のみを購入できる場合の最初の例です。そして反対方向では、今.USもフラットです。レジストリでx.y.z.whatever.us購入するだけwhatever.usで、アルゴリズムは失敗します。
Patrick Mevzek

1
また、(ここでは「セグメント」は2つのドットの間のセクションを意味します):これはDNSの世界ではラベルと呼ばれ、新しい名前を作成する必要はありません。
Patrick Mevzek 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.