Dapatkan subdomain dari URL

101

Mendapatkan subdomain dari URL terdengar mudah pada awalnya.

http://www.domain.example

Pindai periode pertama lalu kembalikan apa pun yang muncul setelah "http: //" ...

Kemudian Anda ingat

http://super.duper.domain.example

Oh. Jadi kemudian Anda berpikir, oke, temukan periode terakhir, mundur satu kata dan dapatkan semuanya sebelumnya!

Kemudian Anda ingat

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

Dan Anda kembali ke titik awal. Adakah yang punya ide bagus selain menyimpan daftar semua TLD?

jb.
sumber
Pertanyaan ini sudah ditanyakan di sini: Mendapatkan Bagian dari URL Edit: Sebuah pertanyaan serupa telah ditanyakan di sini
:)
Cam Anda menjelaskan apa yang Anda inginkan? Tampaknya Anda mencari bagian domain "resmi" dari URL (yaitu domain.co.uk), terlepas dari berapa banyak label DNS yang muncul sebelumnya?
Alnitak
Saya tidak berpikir itu adalah pertanyaan yang sama - ini sepertinya lebih tentang pemotongan administratif dalam nama domain yang tidak dapat diselesaikan hanya dengan melihat stringnya
Alnitak
Saya setuju. Kembangkan lebih lanjut tentang apa tujuan akhir Anda.
BuddyJoe
Lihat jawaban ini: stackoverflow.com/a/39307593/530553
Ehsan Chavoshi

Jawaban:

73

Adakah yang punya ide bagus selain menyimpan daftar semua TLD?

Tidak, karena setiap TLD berbeda dalam hal apa yang dianggap sebagai subdomain, domain level kedua, dll.

Perlu diingat bahwa ada domain level teratas, domain level kedua, dan subdomain. Secara teknis, semua kecuali TLD adalah subdomain.

Dalam contoh domain.com.uk, "domain" adalah subdomain, "com" adalah domain level kedua, dan "uk" adalah TLD.

Jadi pertanyaannya tetap lebih kompleks daripada pada blush pertama, dan itu tergantung pada bagaimana setiap TLD dikelola. Anda akan memerlukan database semua TLD yang menyertakan partisi khusus mereka, dan yang dihitung sebagai domain tingkat kedua dan subdomain. Tidak terlalu banyak TLD, jadi daftarnya dapat dikelola dengan wajar, tetapi mengumpulkan semua informasi itu tidaklah sepele. Mungkin sudah ada daftar seperti itu yang tersedia.

Sepertinya http://publicsuffix.org/ adalah salah satu daftar tersebut — semua sufiks umum (.com, .co.uk, dll) dalam daftar yang sesuai untuk pencarian. Masih tidak akan mudah untuk menguraikannya, tetapi setidaknya Anda tidak perlu mempertahankan daftarnya.

Sebuah "sufiks publik" adalah salah satu di mana pengguna Internet dapat langsung mendaftarkan nama. Beberapa contoh sufiks publik adalah ".com", ".co.uk" dan "pvt.k12.wy.us". Daftar Sufiks Publik adalah daftar semua sufiks publik yang diketahui.

Daftar Sufiks Publik adalah inisiatif dari Mozilla Foundation. Ini tersedia untuk digunakan di perangkat lunak apa pun, tetapi pada awalnya dibuat untuk memenuhi kebutuhan produsen browser. Ini memungkinkan browser untuk, misalnya:

  • Hindari penyetelan "supercookies" yang merusak privasi untuk sufiks nama domain tingkat tinggi
  • Sorot bagian terpenting dari nama domain di antarmuka pengguna
  • Urutkan entri riwayat secara akurat berdasarkan situs

Melihat daftar tersebut , Anda dapat melihat bahwa ini bukanlah masalah yang sepele. Saya pikir daftar adalah satu-satunya cara yang benar untuk mencapai ini ...

Adam Davis
sumber
Mozilla memiliki kode yang menggunakan layanan ini. Proyek ini dipisahkan karena spesifikasi cookie asli telah menghubungkan TLD dengan kepercayaan pada cookie, tetapi tidak pernah berhasil. Bug "Cookie Monster" adalah masalah pertama, dan arsitekturnya tidak pernah diperbaiki atau diganti.
benc
Bahasa yang disukai untuk menyelesaikan masalah ini tidak terdaftar, tetapi ada proyek sumber terbuka yang menggunakan daftar ini dalam kode C # di sini: code.google.com/p/domainname-parser
Dan Esparza
Apakah domain adalah "sufiks publik" atau tidak harus benar-benar tersedia melalui protokol DNS itu sendiri, mungkin melalui tanda EDNS. Dalam hal ini, pemilik dapat menyetelnya, dan tidak perlu menyimpan daftar terpisah.
Pieter Ennes
@PieterEnnes EDNS adalah untuk tanda "terkait pengangkutan", dan tidak dapat digunakan untuk metadata terkait konten. Saya setuju bahwa informasi ini paling baik ditempatkan di DNS itu sendiri. ISTR ada rencana untuk "sesi BoF" di IETF mendatang di Vancouver untuk membahas hal ini.
Alnitak
26

Seperti yang dikatakan Adam, itu tidak mudah, dan saat ini satu-satunya cara praktis adalah menggunakan daftar.

Meskipun demikian, ada pengecualian - misalnya, .ukada beberapa domain yang langsung valid di level tersebut tetapi tidak ada .co.uk, jadi domain tersebut harus ditambahkan sebagai pengecualian.

Beginilah cara browser utama melakukan ini - penting untuk memastikan bahwa example.co.uktidak dapat menetapkan Cookie .co.ukyang kemudian akan dikirim ke situs web lain di bawah .co.uk.

Kabar baiknya adalah sudah ada daftar yang tersedia di http://publicsuffix.org/ .

Ada juga beberapa pekerjaan di IETF untuk membuat semacam standar untuk memungkinkan TLD mendeklarasikan seperti apa struktur domain mereka. Ini agak rumit meskipun oleh .uk.comyang sejenis, yang dioperasikan seolah-olah itu adalah sufiks publik, tetapi tidak dijual oleh .comregistri.

Alnitak
sumber
1
IETF seharusnya tahu lebih baik untuk tidak membiarkan URL mereka mati. Draf (terakhir diperbarui pada Sept 2012) sekarang dapat diakses di sini: tools.ietf.org/html/draft-pettersen-subtld-structure
IMSoP
Kelompok kerja IETF untuk subjek (DBOUND) telah ditutup.
Patrick Mevzek
Perhatikan bahwa sejak saya menulis ini, .ukregistri domain sekarang mengizinkan pendaftaran langsung di tingkat kedua. Hal ini tercermin dalam PSL.
Alnitak
22

Publicsuffix.org sepertinya cara yang harus dilakukan. Ada banyak implementasi di luar sana untuk mengurai konten file data publicsuffix dengan mudah:

JohnTESlade
sumber
2
Tapi ingat ini bukan hanya soal parsing! Daftar di Publicsuffix.org ini adalah proyek tidak resmi, yang tidak lengkap (misalnya eu.org hilang), TIDAK otomatis mencerminkan kebijakan TLD dan mungkin menjadi tidak dipertahankan kapan saja.
bortzmeyer
7
Daftar di publicsuffix.org tidak "tidak resmi" lebih dari apapun yang dilakukan Mozilla. Mengingat Mozilla, Opera, dan Chrome menggunakannya, sepertinya tidak akan terawat. Karena tidak lengkap, setiap operator domain seperti eu.org dapat mengajukan penyertaan jika mereka mau, dan mereka memahami konsekuensi dari melakukannya. Jika Anda ingin domain ditambahkan, minta pemilik untuk melamar. Ya, ini tidak secara otomatis mencerminkan kebijakan TLD, tetapi tidak ada yang mencerminkan - tidak ada sumber programatik dari informasi tersebut.
Gervase Markham
dagger / android: okhttp akan memberikan Anda topPrivateDomain
bladerunner
9

Seperti yang telah dikatakan oleh Adam dan John publicsuffix.org adalah cara yang tepat untuk melakukannya. Namun, jika karena alasan apa pun Anda tidak dapat menggunakan pendekatan ini, berikut adalah heuristik berdasarkan asumsi yang berfungsi untuk 99% dari semua domain:

Ada satu properti yang membedakan (tidak semua, tetapi hampir semua) domain "nyata" dari subdomain dan TLD dan itu adalah data MX DNS. Anda dapat membuat algoritme yang mencari ini: Hapus bagian dari nama host satu per satu dan minta DNS sampai Anda menemukan data MX. Contoh:

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

Berikut adalah contoh di 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");
}
Francois Bourgeois
sumber
Apakah itu yang juga disarankan IETF di sini ?
Ellie Kesselman
1
Bahkan publicsuffix.org mengatakan (lihat paragraf keenam) bahwa cara yang tepat untuk melakukan ini adalah melalui DNS, seperti yang Anda katakan dalam jawaban Anda!
Ellie Kesselman
1
Kecuali Anda dapat sepenuhnya memiliki domain tanpa data MX. Dan algoritme tersebut akan tertipu oleh catatan karakter pengganti. Dan di sisi berlawanan Anda memiliki TLD yang memiliki data MX (seperti .aiatau .axhanya beberapa nama).
Patrick Mevzek
@ patrick: Saya setuju sekali; seperti yang saya katakan dalam pendahuluan, algoritma ini tidak anti peluru, itu hanya heuristik yang bekerja dengan sangat baik.
Francois Bourgeois
2

Seperti yang sudah dikatakan, Daftar Sufiks Publik hanyalah salah satu cara untuk mengurai domain dengan benar. Untuk PHP Anda dapat mencoba TLDExtract . Berikut adalah contoh kode:

$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'
Oleksandr Fediashov
sumber
1

Baru saja menulis program untuk ini di clojure berdasarkan info dari publicsuffix.org:

https://github.com/isaksky/url_dom

Sebagai contoh:

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

Untuk perpustakaan C (dengan pembuatan tabel data dengan Python), saya menulis http://code.google.com/p/domain-registry-provider/ yang cepat dan hemat ruang.

Pustaka menggunakan ~ 30kB untuk tabel data dan ~ 10kB untuk kode C. Tidak ada overhead startup karena tabel dibuat pada waktu kompilasi. Lihat http://code.google.com/p/domain-registry-provider/wiki/DesignDoc untuk detail selengkapnya.

Untuk lebih memahami kode pembuatan tabel (Python), mulailah di sini: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/registry_tables_generator/registry_tables_generator.py

Untuk lebih memahami C API, lihat: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/domain_registry/domain_registry.h

Bryan McQuade
sumber
1
Saya juga memiliki pustaka C / C ++ yang memiliki daftarnya sendiri meskipun ia juga diperiksa terhadap daftar publicsuffix.org. Ini disebut libtld dan bekerja di bawah Unix dan MS-Windows snapwebsites.org/project/libtld
Alexis Wilke
0

Ini tidak berhasil dengan tepat, tetapi Anda mungkin bisa mendapatkan jawaban yang berguna dengan mencoba mengambil domain sepotong demi sepotong dan memeriksa tanggapannya, yaitu, ambil ' http: // uk ', lalu ' http://co.uk ' , lalu ' http://domain.co.uk '. Ketika Anda mendapatkan respon non-error, Anda mendapatkan domain dan sisanya adalah subdomain.

Terkadang Anda harus mencobanya :)

Edit:

Tom Leys menunjukkan di komentar, bahwa beberapa domain hanya diatur di subdomain www, yang akan memberi kami jawaban yang salah dalam tes di atas. Poin bagus! Mungkin pendekatan terbaik adalah memeriksa setiap bagian dengan ' http: // www ' serta 'http: //', dan menghitung hit sebagai klik untuk bagian nama domain tersebut? Kami masih akan kehilangan beberapa pengaturan 'alternatif' seperti 'web.domain.com', tetapi saya belum mengalami salah satunya untuk sementara waktu :)

jTresidder
sumber
Tidak ada jaminan bahwa x.com menunjuk ke server web di port 80 meskipun www.x.com melakukannya. www adalah subdomain yang valid dalam kasus ini. Mungkin whois otomatis akan membantu di sini.
Tom Leys
Poin bagus! Whois akan membersihkannya, meskipun mempertahankan daftar server whois mana yang akan digunakan yang tingkat tld / 2-nya berarti memecahkan masalah yang sama untuk kasus edge.
jTresidder
Anda mengasumsikan bahwa ada menjalankan server HTTP di setiap domain
Francois Bourgeois
Tidak akan berhasil untuk .DKdan beberapa lainnya, sebagaimana http://dk/berfungsi sebagaimana adanya. Heuristik semacam ini bukanlah cara yang tepat ...
Patrick Mevzek
0

Gunakan URIBuilder lalu dapatkan atribut URIBUilder.host membaginya menjadi array di "." Anda sekarang memiliki array dengan domain yang dipisahkan.

jrr
sumber
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;
}
Mike
sumber
0

Anda dapat menggunakan lib ini tld.js: JavaScript API ini untuk bekerja pada nama domain, subdomain, dan URI yang kompleks.

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

Jika Anda mendapatkan domain root di browser. Anda dapat menggunakan lib ini AngusFu / browser-root-domain ini .

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

Menggunakan cookie itu rumit.

xiaoyu2er
sumber
0

Jika Anda ingin mengekstrak subdomain dan / atau domain dari daftar sembarang URL, skrip python ini mungkin bisa membantu. Berhati-hatilah, ini tidak sempurna. Ini adalah masalah yang rumit untuk dipecahkan secara umum dan sangat membantu jika Anda memiliki daftar putih domain yang Anda harapkan.

  1. Dapatkan domain level teratas dari publicsuffix.org
permintaan impor

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

domain = []
untuk baris di halaman.text.splitlines ():
    jika line.startswith ('//'):
        terus
    lain:
        domain = line.strip ()
        jika domain:
            domains.append (domain)

domain = [d [2:] if d.startswith ('*.') else d untuk d dalam domain]
cetak ('domain {} ditemukan'.format (len (domain)))
  1. Bangun regex
impor kembali

_regex = ''
untuk domain di domain:
    _regex + = r '{} |' .format (domain.replace ('.', '\.'))

subdomain_regex = r '/([^/]*)\.[^/.]+\.({})/.*$'. format (_regex)
domain_regex = r '([^ /.] + \. ({})) /.*$'. format (_regex)
  1. Gunakan ekspresi reguler pada daftar URL
FILE_NAME = '' # masukkan nama file CSV di sini
URL_COLNAME = '' # masukkan nama kolom URL di sini

impor panda sebagai pd

df = pd.read_csv (FILE_NAME)
urls = df [URL_COLNAME] .astype (str) + '/' # note: menambahkan / sebagai retasan untuk membantu regex

df ['sub_domain_extracted'] = urls.str.extract (pat = subdomain_regex, luaskan = True) [0]
df ['domain_extracted'] = urls.str.extract (pat = domain_regex, luaskan = Benar) [0]

df.to_csv ('extracted_domains.csv', index = False)
AlexG
sumber
-1

Daftar sufiks umum (.co.uk, .com, dan lain-lain) untuk dihapus bersama dengan http: // dan kemudian Anda hanya akan memiliki "sub.domain" untuk digunakan alih-alih " http: // sub. domain.suffix ", atau setidaknya itulah yang mungkin akan saya lakukan.

Masalah terbesar adalah daftar sufiks yang memungkinkan. Ada banyak sekali.

Peter C.
sumber
-3

Setelah melihat sekilas daftar publicsuffix.org, tampaknya Anda dapat membuat perkiraan yang masuk akal dengan menghapus tiga segmen terakhir ("segmen" di sini berarti bagian antara dua titik) dari domain yang segmen terakhirnya terdiri dari dua karakter, dengan asumsi bahwa itu adalah kode negara dan akan dibagi lagi. Jika segmen terakhir adalah "kami" dan segmen kedua hingga terakhir juga terdiri dari dua karakter, hapus empat segmen terakhir. Di semua kasus lainnya, hapus dua segmen terakhir. misalnya:

"contoh" bukan dua karakter, jadi hapus "domain.example", biarkan "www"

"contoh" bukan dua karakter, jadi hapus "domain.example", biarkan "super.duper"

"uk" adalah dua karakter (tapi bukan "us"), jadi hapus "domain.co.uk", biarkan "super.duper"

"us" adalah dua karakter dan merupakan "us", ditambah "wy" juga dua karakter, jadi hapus "pvt.k12.wy.us", biarkan "foo".

Perhatikan bahwa, meskipun ini berfungsi untuk semua contoh yang telah saya lihat dalam tanggapan sejauh ini, itu tetap hanya perkiraan yang masuk akal. Ini tidak sepenuhnya benar, meskipun saya curiga ini sedekat mungkin yang Anda dapatkan tanpa membuat / mendapatkan daftar aktual untuk digunakan sebagai referensi.

Dave Sherohman
sumber
3
Ada banyak kasus gagal. Ini adalah jenis algoritma browser yang digunakan untuk mencoba dan menggunakan. Jangan lakukan itu, gunakan PSL - ini berfungsi, dan ada perpustakaan untuk membantu Anda.
Gervase Markham
Tidak ada yang melarang gTLD untuk "tersegmentasi" juga, ini terjadi di awal .NAMEmisalnya, ketika Anda hanya dapat membeli firstname.lastname.namenama domain. Dan dalam arah yang berlawanan, sekarang .USjuga datar, jadi Anda dapat memiliki x.y.z.whatever.ushanya dengan membeli whatever.usdi registri dan kemudian algoritme Anda akan gagal.
Patrick Mevzek
1
Juga tentang ("segmen" di sini artinya bagian antara dua titik) : ini disebut label di dunia DNS, tidak perlu membuat nama baru.
Patrick Mevzek