Получить конкретный поддомен из URL в foo.bar.car.com


Задается URL следующим образом:

foo.bar.car.com.au

Мне нужно извлечь foo.bar.

Я наткнулся на следующий код:

private static string GetSubDomain(Uri url)
{
    if (url.HostNameType == UriHostNameType.Dns)
    {
        string host = url.Host;
        if (host.Split('.').Length > 2)
        {
            int lastIndex = host.LastIndexOf(".");
            int index = host.LastIndexOf(".", lastIndex - 1);
            return host.Substring(0, index);
        }
    }         
    return null;     
}

Это дает мне как foo.bar.car. Я хочу фу.бар. Должен ли я просто использовать split и принимать 0 и 1?

Но тогда возможен wwww.

Есть ли простой способ для этого?

7 12

7 ответов:

Учитывая ваше требование (вы хотите 1-й два уровня, не включая ' www.') Я бы подошел к этому примерно так:

private static string GetSubDomain(Uri url)
{

    if (url.HostNameType == UriHostNameType.Dns)
    {

        string host = url.Host;

        var nodes = host.Split('.');
        int startNode = 0;
        if(nodes[0] == "www") startNode = 1;

        return string.Format("{0}.{1}", nodes[startNode], nodes[startNode + 1]);

    }

    return null; 
}

Я столкнулся с подобной проблемой и, основываясь на предыдущих ответах, написал этот метод расширения. Самое главное, он принимает параметр, который определяет" корневой " домен, то есть то, что потребитель метода считает корневым. В случае ОП вызов будет

Uri uri = "foo.bar.car.com.au";
uri.DnsSafeHost.GetSubdomain("car.com.au"); // returns foo.bar
uri.DnsSafeHost.GetSubdomain(); // returns foo.bar.car

Вот метод расширения:

/// <summary>Gets the subdomain portion of a url, given a known "root" domain</summary>
public static string GetSubdomain(this string url, string domain = null)
{
  var subdomain = url;
  if(subdomain != null)
  {
    if(domain == null)
    {
      // Since we were not provided with a known domain, assume that second-to-last period divides the subdomain from the domain.
      var nodes = url.Split('.');
      var lastNodeIndex = nodes.Length - 1;
      if(lastNodeIndex > 0)
        domain = nodes[lastNodeIndex-1] + "." + nodes[lastNodeIndex];
    }

    // Verify that what we think is the domain is truly the ending of the hostname... otherwise we're hooped.
    if (!subdomain.EndsWith(domain))
      throw new ArgumentException("Site was not loaded from the expected domain");

    // Quash the domain portion, which should leave us with the subdomain and a trailing dot IF there is a subdomain.
    subdomain = subdomain.Replace(domain, "");
    // Check if we have anything left.  If we don't, there was no subdomain, the request was directly to the root domain:
    if (string.IsNullOrWhiteSpace(subdomain))
      return null;

    // Quash any trailing periods
    subdomain = subdomain.TrimEnd(new[] {'.'});
  }

  return subdomain;
}

Вы можете использовать следующий пакет nuget Nager.PublicSuffix .

PM> Install-Package Nager.PublicSuffix

Пример

 var domainParser = new DomainParser();
 var data = await domainParser.LoadDataAsync();
 var tldRules = domainParser.ParseRules(data);
 domainParser.AddRules(tldRules);

 var domainName = domainParser.Get("sub.test.co.uk");
 //domainName.Domain = "test";
 //domainName.Hostname = "sub.test.co.uk";
 //domainName.RegistrableDomain = "test.co.uk";
 //domainName.SubDomain = "sub";
 //domainName.TLD = "co.uk";
private static string GetSubDomain(Uri url)
{
    if (url.HostNameType == UriHostNameType.Dns)
    {

        string host = url.Host;   
        String[] subDomains = host.Split('.');
        return subDomains[0] + "." + subDomains[1];
     }
    return null; 
}

Ладно, сначала. Ты специально заглядываешь внутрь? com.au-или это общие доменные имена в Интернете? Потому что если это последнее, то просто нет автоматического способа определить, какая часть домена является "сайтом" или "зоной" или чем-то еще, а какая-то отдельная "хост" или другая запись в этой зоне.

Если вам нужно вычислить это по произвольному доменному имени, вам нужно будет захватить список TLD из проекта Mozilla Public Suffix (http://publicsuffix.org ) и используйте их алгоритм, чтобы найти TLD в вашем доменном имени. Тогда можно предположить, что нужная часть заканчивается последней меткой непосредственно перед дву.

Я бы рекомендовал использовать регулярное выражение. Следующий фрагмент кода должен извлечь то, что вы ищете...

string input = "foo.bar.car.com.au";
var match = Regex.Match(input, @"^\w*\.\w*\.\w*");
var output = match.Value;

В дополнение к NuGet Nager.PubilcSuffix Системы Ответ, Существует также из NuGet Лоу.Пакет PublicSuffix, который согласно своей странице проекта GitHub является библиотекой .Net Core, которая анализирует Public Suffix и основана на Nager.Проект PublicSuffix , со следующими изменениями:

  • портирована на .Чистый основной библиотеки.
  • исправлена библиотека, поэтому она проходит все всесторонние тесты.
  • рефакторинг классов для разделения функциональности на мелкие занятия.
  • классов неизменяемых. Таким образом, DomainParser может использоваться как синглтон и потокобезопасен.
  • добавлены WebTldRuleProvider и FileTldRuleProvider.
  • добавлена возможность узнать, является ли правило правилом ICANN или частным доменом.
  • использовать асинхронную модель программирования

На странице также говорится, что многие из вышеупомянутых изменений были отправлены обратно в оригинал Nager.Проект PublicSuffix .