web-dev-qa-db-ja.com

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

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

http://www.domain.example

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

それから覚えている

http://super.duper.domain.example

ああ。それでは、最後の期間を見つけて、Wordに戻ってすべてを取得することを考えます。

それから覚えている

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

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

100
jb.

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

いいえ、各TLDはサブドメイン、セカンドレベルドメインなどとしてカウントされるものが異なるためです。

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

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

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

http://publicsuffix.org/ はそのようなリストの1つです。検索に適したリスト内のすべての一般的なサフィックス(.com、.co.ukなど)です。それでも解析は簡単ではありませんが、少なくともリストを維持する必要はありません。

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

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

  • 高レベルのドメイン名サフィックスに設定されるプライバシーを損なう「スーパークッキー」を避ける
  • ユーザーインターフェイスでドメイン名の最も重要な部分を強調表示する
  • サイトごとに履歴エントリを正確に並べ替える

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

71
Adam Davis

Adamが言うように、それは簡単ではなく、現在のところ唯一の実用的な方法はリストを使用することです。

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

これは現在、主流のブラウザがこれを行う方法です-_example.co.uk_が_.co.uk_の下にある他のWebサイトに送信される_.co.uk_のCookieを設定できないようにする必要があります。

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

[〜#〜] ietf [〜#〜] には、TLDがドメイン構造の外観を宣言できるようにするための何らかの標準を作成するための作業もあります。ただし、これは_.uk.com_のようなものによってやや複雑になります。これはパブリックサフィックスのように動作しますが、_.com_レジストリでは販売されていません。

26
Alnitak

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

21
JohnTESlade

AdamとJohnが既に言ったように、 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");
}
9

すでに述べたように、 Public Suffix List は、ドメインを正しく解析するための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'
2

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
Isak

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
Bryan McQuade

この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;
    }
  }
};

Cookieの使用には注意が必要です。

0
xiaoyu2er

正確には解決していませんが、ドメインを1つずつフェッチして応答を確認することで、たとえば ' http:// uk 'をフェッチしてから '- http://co.uk '、次に' http://domain.co.uk '。エラー以外の応答を取得すると、ドメインが取得され、残りはサブドメインになります。

ときどき試してみるだけです:)

編集:

トムレイズはコメントの中で、一部のドメインはwwwサブドメインのみに設定されていることを指摘しています。これにより、上記のテストで誤った答えが得られます。いい視点ね!たぶん、最良のアプローチは、「 http:// www 」および「http://」で各部分をチェックし、どちらかのヒットをドメインのそのセクションのヒットとしてカウントすることです名? 「web.domain.com」などの「代替」アレンジメントがまだ不足していますが、しばらくの間それらの1つに遭遇していません:)

0
jTresidder

Objcライブラリを書きました: https://github.com/kejinlu/KKDomain

0
Luke
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
Mike

URIBuilderを使用して、URIBUilder.Host属性を取得し、「。」の配列に分割します。これで、ドメインが分割されたアレイができました。

0
jrr

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

  1. publicsuffix.orgからトップレベルドメインを取得
インポート要求
 
 url = 'https://publicsuffix.org/list/public_suffix_list.dat'
page = requests.get(url)
 
 domains = [] 
 page.text.splitlines()の行:
 if line.startswith( '//'):
 continue 
 else:
 domain = line.strip()
 if domain:
 domains.append(domain)
 
 domains = [ d [2:] if d.startswith( '*。')else d for d in domains] 
 print( 'found {} domains'.format(len(domains)))
  1. 正規表現の構築
 import re 
 
 _ regex = '' 
ドメイン内のドメイン:
 _regex + = r '{} |' .format(domain。 replace( '。'、 '\。'))
 
 subdomain_regex = r '/([^/]*)\.[^/.]+\.({})/。 * $ '。format(_regex)
 domain_regex = r'([^ /。] + \。({}))/.*$ '。format(_regex)
  1. RLのリストで正規表現を使用
 FILE_NAME = ''#ここにCSVファイル名を配置
 URL_COLNAME = ''#ここにURL列名を配置
 
 import pandas = as pd 
 
 df = pd.read_csv(FILE_NAME)
 urls = df [URL_COLNAME] .astype(str)+ '/'#注:/をハックとして追加help regex 
 
 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)
0
AlexG