Holen Sie sich die Subdomain von einer URL

100

Das Abrufen der Subdomain von einer URL klingt zunächst einfach.

http://www.domain.example

Scannen Sie für den ersten Zeitraum und geben Sie dann alles zurück, was nach dem "http: //" ...

Dann erinnerst du dich

http://super.duper.domain.example

Oh. Dann denkst du, okay, finde die letzte Periode, geh ein Wort zurück und hol alles vorher!

Dann erinnerst du dich

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

Und du bist wieder auf dem ersten Platz. Hat jemand gute Ideen, außer eine Liste aller TLDs zu speichern?

jb.
quelle
Diese Frage wurde hier bereits gestellt: Teile einer URL abrufen Bearbeiten: Eine ähnliche Frage wurde hier gestellt
:)
Cam Sie klären, was Sie wollen? Es scheint, dass Sie nach dem "offiziellen" Domain-Teil der URL (dh domain.co.uk) suchen, unabhängig davon, wie viele DNS-Labels davor erscheinen?
Alnitak
Ich denke nicht, dass es die gleiche Frage ist - dies scheint mehr über die administrativen Kürzungen im Domain-Namen zu sein, die nicht einfach durch Betrachten der Zeichenfolge herausgearbeitet werden können
Alnitak
Genau. Erweitern Sie mehr über Ihr Endziel.
BuddyJoe
Siehe diese Antwort: stackoverflow.com/a/39307593/530553
Ehsan Chavoshi

Antworten:

73

Hat jemand gute Ideen, außer eine Liste aller TLDs zu speichern?

Nein, da sich jede TLD darin unterscheidet, was als Subdomain, Second Level Domain usw. zählt.

Beachten Sie, dass es Domänen der obersten Ebene, Domänen der zweiten Ebene und Unterdomänen gibt. Technisch gesehen ist alles außer der TLD eine Subdomain.

Im Beispiel domain.com.uk ist "domain" eine Subdomain, "com" eine Domain der zweiten Ebene und "uk" die TLD.

Die Frage bleibt also komplexer als auf den ersten Blick und hängt davon ab, wie jede TLD verwaltet wird. Sie benötigen eine Datenbank aller TLDs, die ihre jeweilige Partitionierung enthalten, sowie eine Datenbank der zweiten Ebene und eine Subdomäne. Es gibt jedoch nicht zu viele TLDs, sodass die Liste einigermaßen überschaubar ist, aber das Sammeln all dieser Informationen ist nicht trivial. Möglicherweise ist eine solche Liste bereits verfügbar.

Es sieht so aus, als ob http://publicsuffix.org/ eine solche Liste ist - alle gängigen Suffixe (.com, .co.uk usw.) in einer Liste, die für die Suche geeignet ist. Es wird immer noch nicht einfach sein, es zu analysieren, aber zumindest müssen Sie die Liste nicht pflegen.

Ein "öffentliches Suffix" ist eines, unter dem Internetbenutzer Namen direkt registrieren können. Einige Beispiele für öffentliche Suffixe sind ".com", ".co.uk" und "pvt.k12.wy.us". Die öffentliche Suffixliste ist eine Liste aller bekannten öffentlichen Suffixe.

Die Public Suffix List ist eine Initiative der Mozilla Foundation. Es kann in jeder Software verwendet werden, wurde jedoch ursprünglich entwickelt, um die Anforderungen der Browserhersteller zu erfüllen. Es ermöglicht Browsern zum Beispiel:

  • Vermeiden Sie, dass datenschutzschädigende "Supercookies" für Domain-Suffixe auf hoher Ebene festgelegt werden
  • Markieren Sie den wichtigsten Teil eines Domainnamens in der Benutzeroberfläche
  • Sortieren Sie Verlaufseinträge genau nach Site

Wenn Sie die Liste durchsehen, sehen Sie, dass dies kein triviales Problem ist. Ich denke, eine Liste ist der einzig richtige Weg, um dies zu erreichen ...

Adam Davis
quelle
Mozilla hat Code, der diesen Dienst verwendet. Das Projekt wurde ausgegliedert, weil die ursprüngliche Cookie-Spezifikation TLDs mit dem Vertrauen in Cookies verknüpft hatte, aber nie funktionierte. Der "Cookie Monster" -Fehler war das erste Problem, und die Architektur wurde nie behoben oder ersetzt.
Benc
Die bevorzugte Sprache, um dies zu lösen, ist nicht aufgeführt, aber es gibt ein OpenSource-Projekt, das diese Liste im C # -Code hier verwendet: code.google.com/p/domainname-parser
Dan Esparza
Ob eine Domain ein "öffentliches Suffix" ist oder nicht, sollte wirklich über das DNS-Protokoll selbst verfügbar gemacht werden, möglicherweise über ein EDNS-Flag. In diesem Fall kann der Eigentümer dies festlegen, und es ist nicht erforderlich, eine separate Liste zu führen.
Pieter Ennes
@PieterEnnes EDNS steht für "transportbezogene" Flags und kann nicht für inhaltsbezogene Metadaten verwendet werden. Ich bin damit einverstanden, dass diese Informationen am besten im DNS selbst platziert werden. ISTR gibt es Pläne für eine "BoF-Sitzung" auf der kommenden IETF in Vancouver, um dies zu diskutieren.
Alnitak
26

Wie Adam sagt, ist es nicht einfach und derzeit ist der einzige praktische Weg, eine Liste zu verwenden.

Selbst dann gibt es Ausnahmen - zum Beispiel .ukgibt es eine Handvoll Domänen, die auf dieser Ebene sofort gültig sind und nicht in der Domäne enthalten sind. Daher .co.ukmüssen diese als Ausnahmen hinzugefügt werden.

So machen es derzeit Mainstream-Browser - es muss sichergestellt werden, dass example.co.ukkein Cookie gesetzt werden kann, für .co.ukdas dann eine andere Website unter gesendet wird .co.uk.

Die gute Nachricht ist, dass unter http://publicsuffix.org/ bereits eine Liste verfügbar ist .

In der IETF gibt es auch einige Arbeiten , um eine Art Standard zu erstellen, mit dem TLDs deklarieren können, wie ihre Domänenstruktur aussieht. Dies ist zwar etwas kompliziert .uk.com, wird jedoch wie ein öffentliches Suffix betrieben, aber nicht von der .comRegistrierung verkauft.

Alnitak
quelle
1
Eugh, die IETF sollte es besser wissen, als ihre URLs sterben zu lassen. Der Entwurf (zuletzt aktualisiert im September 2012) kann jetzt hier erreicht werden: tools.ietf.org/html/draft-pettersen-subtld-structure
IMSoP
Die IETF-Arbeitsgruppe zu diesem Thema (DBOUND) wurde geschlossen.
Patrick Mevzek
Beachten Sie, dass die .ukDomain-Registrierung , seit ich dies geschrieben habe , Registrierungen direkt auf der zweiten Ebene zulässt. Dies spiegelt sich entsprechend in der PSL wider.
Alnitak
22

Publicsuffix.org scheint der richtige Weg zu sein. Es gibt viele Implementierungen, mit denen der Inhalt der Datei mit den öffentlichen Datendateien einfach analysiert werden kann:

JohnTESlade
quelle
2
Aber denken Sie daran, es geht nicht nur um das Parsen! Diese Liste auf Publicsuffix.org ist ein inoffizielles Projekt, das unvollständig ist (z. B. fehlt eu.org), die Richtlinien von TLD NICHT automatisch widerspiegelt und jederzeit nicht mehr gepflegt werden kann.
Bortzmeyer
7
Die Liste auf publicsuffix.org ist nicht mehr als alles andere, was Mozilla tut, "inoffiziell". Angesichts der Tatsache, dass Mozilla, Opera und Chrome es verwenden, ist es unwahrscheinlich, dass es nicht mehr gewartet wird. Als unvollständig kann jeder Betreiber einer Domain wie eu.org die Aufnahme beantragen, wenn er möchte, und er versteht die Konsequenzen, die sich daraus ergeben. Wenn Sie eine Domain hinzufügen möchten, lassen Sie den Eigentümer sich bewerben. Ja, es spiegelt nicht automatisch die TLD-Richtlinie wider, aber nichts - es gibt keine programmatische Quelle für diese Informationen.
Gervase Markham
Dolch / Android: okhttp gibt Ihnen topPrivateDomain
Bladerunner
9

Wie bereits von Adam und John gesagt, ist publicsuffix.org der richtige Weg. Wenn Sie diesen Ansatz jedoch aus irgendeinem Grund nicht verwenden können, finden Sie hier eine Heuristik, die auf einer Annahme basiert, die für 99% aller Domänen funktioniert:

Es gibt eine Eigenschaft, die (nicht alle, aber fast alle) "echte" Domänen von Subdomänen und TLDs unterscheidet, und das ist der MX-Eintrag des DNS. Sie können einen Algorithmus erstellen, der danach sucht: Entfernen Sie die Teile des Hostnamens nacheinander und fragen Sie den DNS ab, bis Sie einen MX-Eintrag finden. Beispiel:

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

Hier ist ein Beispiel in 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
quelle
Schlägt die IETF dies auch hier vor ?
Ellie Kesselman
1
Sogar publicsuffix.org sagt (siehe sechster Absatz), dass der richtige Weg, dies zu tun, über das DNS erfolgt, genau wie Sie es in Ihrer Antwort gesagt haben!
Ellie Kesselman
1
Abgesehen davon, dass Sie eine Domain ohne MX-Eintrag vollständig haben können. Und dass der Algorithmus durch Platzhalterdatensätze getäuscht wird. Und auf der anderen Seite haben Sie TLDs mit MX-Datensätzen (wie .aioder .axum nur einige zu nennen).
Patrick Mevzek
@patrick: Ich stimme vollkommen zu; Wie ich in der Einleitung sagte, ist dieser Algorithmus nicht kugelsicher, sondern nur eine Heuristik, die überraschend gut funktioniert.
Francois Bourgeois
2

Wie bereits erwähnt, ist die öffentliche Suffixliste nur eine Möglichkeit, die Domain korrekt zu analysieren. Für PHP können Sie TLDExtract ausprobieren . Hier ist Beispielcode:

$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
quelle
1

Habe gerade ein Programm dafür in Clojure geschrieben, basierend auf den Informationen von publicsuffix.org:

https://github.com/isaksky/url_dom

Beispielsweise:

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

Für eine C-Bibliothek (mit Datentabellengenerierung in Python) habe ich http://code.google.com/p/domain-registry-provider/ geschrieben. was sowohl schnell als auch platzsparend ist.

Die Bibliothek verwendet ~ 30 KB für die Datentabellen und ~ 10 KB für den C-Code. Es gibt keinen Startaufwand, da die Tabellen zur Kompilierungszeit erstellt werden. Weitere Informationen finden Sie unter http://code.google.com/p/domain-registry-provider/wiki/DesignDoc .

Beginnen Sie hier, um den Code zur Tabellengenerierung (Python) besser zu verstehen: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/registry_tables_generator/registry_tables_generator.py

Weitere Informationen zur C-API finden Sie unter: http://code.google.com/p/domain-registry-provider/source/browse/trunk/src/domain_registry/domain_registry.h

Bryan McQuade
quelle
1
Ich habe auch eine C / C ++ - Bibliothek, die eine eigene Liste hat, obwohl sie auch mit der Liste publicsuffix.org verglichen wird. Es heißt libtld und funktioniert unter Unix und MS-Windows snapwebsites.org/project/libtld
Alexis Wilke
0

Es funktioniert nicht genau, aber Sie könnten vielleicht eine nützliche Antwort erhalten, indem Sie versuchen, die Domain Stück für Stück abzurufen und die Antwort zu überprüfen, dh ' http: // uk ' und dann ' http://co.uk ' abrufen. , dann ' http://domain.co.uk '. Wenn Sie eine fehlerfreie Antwort erhalten, haben Sie die Domain und der Rest ist die Subdomain.

Manchmal musst du es einfach versuchen :)

Bearbeiten:

Tom Leys weist in den Kommentaren darauf hin, dass einige Domains nur in der WWW-Subdomain eingerichtet sind, was uns im obigen Test eine falsche Antwort geben würde. Guter Punkt! Vielleicht wäre der beste Ansatz, jedes Teil mit ' http: // www ' sowie 'http: //' zu überprüfen und einen Treffer als Treffer für diesen Abschnitt des Domainnamens zu zählen? Wir würden immer noch einige "alternative" Arrangements wie "web.domain.com" vermissen, aber ich habe eine Weile keine davon getroffen :)

jTresidder
quelle
Es gibt keine Garantie dafür, dass x.com auf einen Webserver an Port 80 verweist, selbst wenn dies bei www.x.com der Fall ist. www ist in diesem Fall eine gültige Subdomain. Vielleicht würde hier ein automatisierter Whois helfen.
Tom Leys
Guter Punkt! Ein whois würde es klären, obwohl das Führen einer Liste, welche whois-Server für welche für welche tld / 2nd-Ebene verwendet werden sollen, das Lösen des gleichen Problems für Randfälle bedeuten würde.
jTresidder
Sie gehen davon aus, dass in jeder Domain ein HTTP-Server ausgeführt wird
Francois Bourgeois
Funktioniert nicht für .DKund einige andere, so http://dk/wie es ist. Diese Art von Heuristiken sind nicht der
richtige
0

Verwenden Sie den URIBuilder und rufen Sie das Attribut URIBUilder.host auf, und teilen Sie es in ein Array auf "." Sie haben jetzt ein Array mit der Domain aufgeteilt.

jrr
quelle
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
quelle
0

Sie können diese lib tld.js: JavaScript-API verwenden, um mit komplexen Domänennamen, Subdomänen und URIs zu arbeiten.

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

Wenn Sie eine Root-Domain im Browser erhalten. Sie können diese lib AngusFu / browser-root-Domain verwenden .

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

Die Verwendung von Cookies ist schwierig.

xiaoyu2er
quelle
0

Wenn Sie Subdomains und / oder Domains aus einer beliebigen Liste von URLs extrahieren möchten, kann dieses Python-Skript hilfreich sein. Sei aber vorsichtig, es ist nicht perfekt. Dies ist ein schwieriges Problem, das im Allgemeinen gelöst werden muss. Es ist sehr hilfreich, wenn Sie eine Whitelist mit Domains haben, die Sie erwarten.

  1. Holen Sie sich Top-Level-Domains von publicsuffix.org
Importanforderungen

url = 'https://publicsuffix.org/list/public_suffix_list.dat'
page = request.get (url)

Domains = []
für Zeile in page.text.splitlines ():
    if line.startswith ('//'):
        fortsetzen
    sonst:
        domain = line.strip ()
        if domain:
            Domains.append (Domain)

Domains = [d [2:] wenn d.startswith ('*.') sonst d für d in Domains]
print ('gefundene {} Domains'.format (len (Domains)))
  1. Erstellen Sie Regex
import re

_regex = ''
für Domain in Domains:
    _regex + = r '{} |' .format (domain.replace ('.', '\.'))

subdomain_regex = r '/([^/‹*)\.[^/. weibl.
domain_regex = r '([^ /.] + \. ({})) /.*$'. format (_regex)
  1. Verwenden Sie Regex für die Liste der URLs
FILE_NAME = '' # Geben Sie hier den Namen der CSV-Datei ein
URL_COLNAME = '' # Geben Sie hier den Namen der URL-Spalte ein

Pandas als pd importieren

df = pd.read_csv (FILE_NAME)
urls = df [URL_COLNAME] .astype (str) + '/' # Hinweis: Hinzufügen von / als Hack zur Unterstützung der 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 ('extract_domains.csv', index = False)
AlexG
quelle
-1

Liste der gebräuchlichen Suffixe (.co.uk, .com usw.), die zusammen mit http: // entfernt werden sollen, und dann haben Sie nur "sub.domain" zum Arbeiten anstelle von " http: // sub". domain.suffix ", oder zumindest würde ich das wahrscheinlich tun.

Das größte Problem ist die Liste möglicher Suffixe. Es gibt schließlich viel.

Peter C.
quelle
-3

Nach einem kurzen Blick auf die Liste publicsuffix.org scheint es, als könnten Sie eine vernünftige Annäherung vornehmen, indem Sie die letzten drei Segmente ("Segment" bedeutet hier einen Abschnitt zwischen zwei Punkten) aus Domänen entfernen, in denen das letzte Segment zwei Zeichen lang ist. unter der Annahme, dass es sich um einen Ländercode handelt, der weiter unterteilt wird. Wenn das letzte Segment "wir" ist und das vorletzte Segment ebenfalls aus zwei Zeichen besteht, entfernen Sie die letzten vier Segmente. In allen anderen Fällen entfernen Sie die letzten beiden Segmente. z.B:

"Beispiel" besteht nicht aus zwei Zeichen. Entfernen Sie daher "domain.example" und lassen Sie "www".

"Beispiel" besteht nicht aus zwei Zeichen. Entfernen Sie daher "domain.example" und lassen Sie "super.duper".

"uk" besteht aus zwei Zeichen (aber nicht "wir"). Entfernen Sie daher "domain.co.uk" und lassen Sie "super.duper".

"us" besteht aus zwei Zeichen und ist "us". "wy" besteht ebenfalls aus zwei Zeichen. Entfernen Sie daher "pvt.k12.wy.us" und lassen Sie "foo".

Beachten Sie, dass dies zwar für alle Beispiele funktioniert, die ich bisher in den Antworten gesehen habe, aber nur eine vernünftige Annäherung bleibt. Es ist nicht ganz korrekt, obwohl ich vermute, dass es ungefähr so ​​nah ist, wie es wahrscheinlich ist, ohne eine tatsächliche Liste zu erstellen / zu erhalten, die als Referenz verwendet werden kann.

Dave Sherohman
quelle
3
Es gibt viele Fehlerfälle. Dies ist die Art von Algorithmus-Browsern, mit denen versucht wird, sie zu verwenden. Tun Sie das nicht, verwenden Sie die PSL - es funktioniert und es gibt Bibliotheken, die Ihnen helfen.
Gervase Markham
Nichts verbietet auch die "Segmentierung" von gTLDs. Dies war beispielsweise zu Beginn der Zeit der Fall .NAME, als Sie nur firstname.lastname.nameDomain-Namen kaufen konnten . Und in entgegengesetzter Richtung ist jetzt .USauch flach, so dass Sie nur x.y.z.whatever.usdurch den Kauf whatever.usbei der Registrierung haben können und dann Ihr Algorithmus darauf fehlschlagen wird.
Patrick Mevzek
1
Auch über ("Segment" bedeutet hier einen Abschnitt zwischen zwei Punkten) : Dies wird in der DNS-Welt als Bezeichnung bezeichnet, ohne dass ein neuer Name erfunden werden muss.
Patrick Mevzek