在C#中提取URL中的域名

5

这个问题在其他语言/平台上已经有答案,但我在C#中找不到一个强大的解决方案。在这里,我正在寻找我们在WHOIS中使用的URL部分,因此我对子域,端口,模式等不感兴趣。

Example 1: http://s1.website.co.uk/folder/querystring?key=value => website.co.uk
Example 2: ftp://username:password@website.com => website.com

当whois中的所有者相同时,sub1.xyz.com和sub2.xyz.com的结果应该是相同的,因此它们都属于拥有xyz.com的人,我需要从URL中提取。

4个回答

5

我也有同样的需求,所以我编写了一个类,你可以将其复制并粘贴到你的解决方案中。它使用了一个硬编码的顶级域名字符串数组。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


感谢分享你的工作。另一个问题是保持列表更新,但我认为它不会经常改变。 - Xaqron
这个类很棒。我已经从PublicSuffix列表中清单了所有TLDs,今天更新。它几乎比你提交的那个大两倍(约6390个条目)。如果您需要,可以在http://pastebin.com/raw.php?i=PxKWw5jt找到变量。 :) 再次感谢! :) - moskalak
1
现在没有任何链接可用。 - venkat balabhadra

3

正如@Pete所指出的,这有点复杂,但我会试着解释一下。

请注意,此应用程序必须包含已知TLD的完整列表。 这些可以从http://publicsuffix.org/检索。 从该网站提取列表留给读者作为练习。

class Program
{
    static void Main(string[] args)
    {
        var testCases = new[]
        {
            "www.domain.com.ac",
            "www.domain.ac",
            "domain.com.ac",
            "domain.ac",
            "localdomain",
            "localdomain.local"
        };

        foreach (string testCase in testCases)
        {
            Console.WriteLine("{0} => {1}", testCase, UriHelper.GetDomainFromUri(new Uri("http://" + testCase + "/")));
        }

        /* Produces the following results:

            www.domain.com.ac => domain.com.ac
            www.domain.ac => domain.ac
            domain.com.ac => domain.com.ac
            domain.ac => domain.ac
            localdomain => localdomain
            localdomain.local => localdomain.local
         */
    }
}

public static class UriHelper
{
    private static HashSet<string> _tlds;

    static UriHelper()
    {
        _tlds = new HashSet<string>
        {
            "com.ac",
            "edu.ac",
            "gov.ac",
            "net.ac",
            "mil.ac",
            "org.ac",
            "ac"

            // Complete this list from http://publicsuffix.org/.
        };
    }

    public static string GetDomainFromUri(Uri uri)
    {
        return GetDomainFromHostName(uri.Host);
    }

    public static string GetDomainFromHostName(string hostName)
    {
        string[] hostNameParts = hostName.Split('.');

        if (hostNameParts.Length == 1)
            return hostNameParts[0];

        int matchingParts = FindMatchingParts(hostNameParts, 1);

        return GetPartOfHostName(hostNameParts, hostNameParts.Length - matchingParts);
    }

    private static int FindMatchingParts(string[] hostNameParts, int offset)
    {
        if (offset == hostNameParts.Length)
            return hostNameParts.Length;

        string domain = GetPartOfHostName(hostNameParts, offset);

        if (_tlds.Contains(domain.ToLowerInvariant()))
            return (hostNameParts.Length - offset) + 1;

        return FindMatchingParts(hostNameParts, offset + 1);
    }

    private static string GetPartOfHostName(string[] hostNameParts, int offset)
    {
        var sb = new StringBuilder();

        for (int i = offset; i < hostNameParts.Length; i++)
        {
            if (sb.Length > 0)
                sb.Append('.');

            sb.Append(hostNameParts[i]);
        }

        string domain = sb.ToString();
        return domain;
    }
}

@Xaqron - 我不明白。我已将整个代码复制到了一个新的控制台项目中,它可以正确编译并给出预期结果。您能否更具体地说明您认为缺少什么? - Pieter van Ginkel
GetDomainFromHostName() 方法下面缺少了 jest,但现在已经添加上了。谢谢。 - Xaqron

1

最接近的方法是使用System.Uri.Host属性,该属性可以提取sub1.xyz.com部分。不幸的是,很难确定主机的“顶级”部分是什么(例如sub1.foo.co.uk与sub1.xyz.com)。


几乎不可能确定哪个是顶级域名,因为例如.co.uk需要两个部分,但.info或.jp需要除.[a-zA-Z]{3}之外的其他内容。 - jcolebrand
可以使用公共后缀列表来完成这种任务。但最简单的方法可能是对整个主机名进行whois查询,并逐段处理直到获得结果。 - bobince
那个列表“应该”是正确的,但这就是我的观点。 “应该”不是一个很好的业务规则... - jcolebrand
@bobince 是的,这可能是最可靠的方法,逐步处理各个段。 - Pete

0

如果你需要域名,那么你可以在 .net 中使用 URi.hostadress。

如果你需要从内容中获取 URL,则需要使用正则表达式进行解析。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接