繁体   English   中英

仅从 URL 获取域名?

[英]Get just the domain name from a URL?

我试图从 URL 字符串中提取域名。 我几乎拥有它...我正在使用 URI

我有一个字符串..我的第一个想法是使用 Regex 但后来我决定使用 URI 类

http://www.google.com/url?sa=t&source=web&ct=res&cd=1&ved=0CAgQFjAA&url=http://www.test.com/&rct=j&q=test&ei=G2phS-HdJJWTjAfckvHJDA&usg=AFQjCNFSEAztaqtkaIvEzOxmRmRm

我需要将上述内容转换为 google.com 和 google 而不带 www

我做了以下

Uri test = new Uri(referrer);
log.Info("Domain part : " + test.Host);

基本上这会返回 www.google.com .... 如果可能的话,我想尝试返回 2 个表单......如上所述......

google.com 和谷歌

这可以通过 URI 实现吗?

是的,可以使用:

Uri.GetLeftPart( UriPartial.Authority )

@Dewfy:缺陷是您的方法为“www.test.co.uk”返回“uk”,但这里的域显然是“test.co.uk”。

@naivists:缺陷是您的方法为“www.beta.microsoft.com”返回“beta.microsoft.com”,但此处的域显然是“microsoft.com”

我需要同样的东西,所以我写了一个类,您可以将其复制并粘贴到您的解决方案中。 它使用 tld 的硬编码字符串数组。 http://pastebin.com/raw.php?i=VY3DCNhp

Console.WriteLine(GetDomain.GetDomainFromUrl("http://www.beta.microsoft.com/path/page.htm"));

输出microsoft.com

Console.WriteLine(GetDomain.GetDomainFromUrl("http://www.beta.microsoft.co.uk/path/page.htm"));

输出microsoft.co.uk

google.com 不能保证与 www.google.com 相同(好吧,对于这个例子,它在技术上是一样的,但可能不是)。

也许您需要的是删除“顶级”域和“www”子域? 然后只需split('.')并在最后一部分之前取部分!

我尝试了几乎所有方法,但都没有达到预期的结果。 所以这是我从 servermanfail 调整的方法。

tld 文件可在https://publicsuffix.org/list/ 上找到我从https://publicsuffix.org/list/effective_tld_names.dat获取文件,解析它并搜索 tld。 如果发布了新的 tld,只需下载最新的文件。

玩得开心。

using System;
using System.Collections.Generic;
using System.IO;

namespace SearchWebsite
{
internal class NetDomain
{
    static public string GetDomainFromUrl(string Url)
    {
        return GetDomainFromUrl(new Uri(Url));
    }

    static public string GetDomainFromUrl(string Url, bool Strict)
    {
        return GetDomainFromUrl(new Uri(Url), Strict);
    }

    static public string GetDomainFromUrl(Uri Url)
    {
        return GetDomainFromUrl(Url, false);
    }

    static public string GetDomainFromUrl(Uri Url, bool Strict)
    {
        initializeTLD();
        if (Url == null) return null;
        var dotBits = Url.Host.Split('.');
        if (dotBits.Length == 1) return Url.Host; //eg http://localhost/blah.php = "localhost"
        if (dotBits.Length == 2) return Url.Host; //eg http://blah.co/blah.php = "localhost"
        string bestMatch = "";
        foreach (var tld in DOMAINS)
        {
            if (Url.Host.EndsWith(tld, StringComparison.InvariantCultureIgnoreCase))
            {
                if (tld.Length > bestMatch.Length) bestMatch = tld;
            }
        }
        if (string.IsNullOrEmpty(bestMatch))
            return Url.Host; //eg http://domain.com/blah = "domain.com"

        //add the domain name onto tld
        string[] bestBits = bestMatch.Split('.');
        string[] inputBits = Url.Host.Split('.');
        int getLastBits = bestBits.Length + 1;
        bestMatch = "";
        for (int c = inputBits.Length - getLastBits; c < inputBits.Length; c++)
        {
            if (bestMatch.Length > 0) bestMatch += ".";
            bestMatch += inputBits[c];
        }
        return bestMatch;
    }


    static private void initializeTLD()
    {
        if (DOMAINS.Count > 0) return;

        string line;
        StreamReader reader = File.OpenText("effective_tld_names.dat");
        while ((line = reader.ReadLine()) != null)
        {
            if (!string.IsNullOrEmpty(line) && !line.StartsWith("//"))
            {
                DOMAINS.Add(line);
            }
        }
        reader.Close();
    }


    // This file was taken from https://publicsuffix.org/list/effective_tld_names.dat

    static public List<String> DOMAINS = new List<String>();
}

}

下面是一些仅提供 SLD 加 gTLD 或 ccTLD 扩展名的代码(请注意下面的例外情况)。 我不在乎 DNS。

该理论如下:

  • 3 个令牌以下的任何内容保持原样,例如“localhost”、“domain.com”,否则:最后一个令牌必须是 gTLD 或 ccTLD 扩展名。
  • 如果倒数第二个标记的长度 < 3 或包含在异常列表中,则将其视为扩展的一部分。
  • 最后,在那个之前的令牌被认为是 SLD。 在此之前的任何内容都被视为子域或主机限定符,例如 Www。

至于代码,简短而甜蜜:

private static string GetDomainName(string url)
{
    string domain = new Uri(url).DnsSafeHost.ToLower();
    var tokens = domain.Split('.');
    if (tokens.Length > 2)
    {
        //Add only second level exceptions to the < 3 rule here
        string[] exceptions = { "info", "firm", "name", "com", "biz", "gen", "ltd", "web", "net", "pro", "org" }; 
        var validTokens = 2 + ((tokens[tokens.Length - 2].Length < 3 || exceptions.Contains(tokens[tokens.Length - 2])) ? 1 : 0);
        domain = string.Join(".", tokens, tokens.Length - validTokens, validTokens);
    }
    return domain;
}

明显的例外是这不会处理 2 个字母的域名。 因此,如果您有幸拥有 ab.com,则需要稍微调整代码。 对于我们这些凡人来说,此代码将涵盖几乎所有 gTLD 和 ccTLD,减去一些非常奇特的。

我认为您对“域名”的构成存在误解 - 没有常见的“纯域名”这样的东西 - 如果您想要一致的结果,您需要定义这一点。
你只是想去掉“www”部分吗? 然后有另一个版本剥离顶级域(例如剥离“.com”或“.co.uk”等部分?)另一个答案提到 split(".") - 你需要使用一些东西像这样,如果您想手动排除主机名的特定部分,.NET 框架中没有任何内容可以完全满足您的要求 - 您需要自己实现这些内容。

最近看到Rick Strahl的博客作为一些c#和.net中心的参考:

理解ASP.NET路径

使用 Nager.PublicSuffix

安装包 Nager.PublicSuffix

var domainParser = new DomainParser(new WebTldRuleProvider());

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

是的,我在这里发布了解决方案: http : //pastebin.com/raw.php?i=raxNQkCF

如果您想删除扩展名,只需添加

if (url.indexof(".")>-1) {url = url.substring(0, url.indexof("."))}

Uri 的主机总是返回域 (www.google.com),包括一个标签 (www) 和一个顶级域 (com)。 但通常你会想要提取中间位。 只是我做

Uri uri;
bool result = Uri.TryCreate(returnUri, UriKind.Absolute, out uri);
if (result == false)
    return false;

//if you are sure it's not "localhost"
string domainParts = uri.Host.Split('.');
string topLevel = domainParts[domainParts.Length - 1]
string hostBody = domainParts[domainParts.Length - 2]
string label = domainParts[domainParts.Length - 3]

但是您确实需要检查 domainParts.length,因为给定的 uri 通常类似于“google.com”。

我想出了以下解决方案(使用 Linq):

    public string MainDomainFromHost(string host)
    {
        string[] parts = host.Split('.');
        if (parts.Length <= 2)
            return host; // host is probably already a main domain
        if (parts[parts.Length - 1].All(char.IsNumber))
            return host; // host is probably an IPV4 address
        if (parts[parts.Length - 1].Length == 2 && parts[parts.Length - 2].Length == 2)
            return string.Join(".", parts.TakeLast(3)); // this is the case for co.uk, co.in, etc...
        return string.Join(".", parts.TakeLast(2)); // all others, take only the last 2
    }

我为自己找到了一个解决方案,这不使用任何 TLD 或其他东西。

它使用了这样一个事实,即所谓的主机名在 Uri 的主机部分中总是在倒数第二个位置。 子域始终在名称前面,TLD 始终在其后面。

看这里:

private static string GetNameFromHost(string host)
{
    if (host.Count(f => f == '.') == 1)
    {
        return host.Split('.')[0];
    }
    else
    {
        var _list = host.Split('.').ToList();
        return _list.ElementAt(_list.Count - 2);
    }
}

由于域名的众多变化以及您所描述的构成“纯域名”的任何真正权威列表的不存在,我过去只是使用 Uri.Host。 为避免 www.google.com 和 google.com 显示为两个不同的域的情况,我经常采取去除 www 的方法。 来自包含它的所有域,因为几乎可以保证(几乎)指向同一个站点。 这确实是唯一一种不会丢失一些数据的简单方法。

string domain = new Uri(HttpContext.Current.Request.Url.AbsoluteUri).GetLeftPart(UriPartial.Authority);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM