从给定的URL中提取主域名

13

我使用以下代码从url中提取域名(这是测试用例):

String regex = "^(ww[a-zA-Z0-9-]{0,}\\.)";
ArrayList<String> cases = new ArrayList<String>();
cases.add("www.google.com");
cases.add("ww.socialrating.it");
cases.add("www-01.hopperspot.com");
cases.add("wwwsupernatural-brasil.blogspot.com");
cases.add("xtop10.net");
cases.add("zoyanailpolish.blogspot.com");

for (String t : cases) {  
    String res = t.replaceAll(regex, "");  
}

我可以得到以下结果:

google.com
hopperspot.com
socialrating.it
blogspot.com
xtop10.net
zoyanailpolish.blogspot.com

前四种情况都是好的,最后一种不好。我想要的是:最后一个使用 blogspot.com,但实际上它给出了zoyanailpolish.blogspot.com。我做错了什么?

1
看起来这篇帖子中的正则表达式可能会对你有所帮助 =) - Josh Darnell
2
那就不要在你的模式中放置那些傻傻的woublewoos。如果您只想s/^[^.]+\.//,那我建议您这样做。 - tchrist
2
不太清楚你想要什么。你是想删除第一个组件“always”,还是除了TLD之前的那个组件以外的所有组件,或者只有当第一个组件以“ww”开头时才删除它? - Ray Toal
8
هƒڈexample.com.twه’Œexample.co.ukè؟™و ·çڑ„هںںهگچو€ژن¹ˆو ·ï¼ں - BalusC
3
不要用复杂的正则表达式方法。使用正则表达式解决这种问题是荒谬的。按点拆分成数组,计算部分数量。检查倒数第二个部分的长度是否不小于3个字符和/或是否以“co”开头(可能还有其他您想匹配的ccTLDs)。根据结果获取最后两个或三个项目,并再次使用点连接它们。 - BalusC
显示剩余12条评论
7个回答

14

8

通过正则表达式获取主机名是相当复杂或不可能的,因为顶级域名不遵守简单规则,而是由ICANN提供并随时间变化。

相反,您应该使用JAVA库提供的功能,如下所示:

URL myUrl = new URL(urlString);
myUrl.getHost();

1
嗯,是的,但他已经拥有所有的那些了。他想要有时将一些小端主机名的前导元素移开,尽管他没有告诉我们可能会有多少个。他似乎认为我们可以直观地判断域名是否已经包含了“主要”部分。我不认为这是可能的。 - tchrist
9
记录一下,这并没有回答问题。它返回给定的域名,包括子域名。原帖作者正在寻找不带子域名的“根”域名,因此如果给定“www.google.com”,它应该返回“google.com”。这种方法返回“www.google.com”。如果你只是想从带有路径和/或查询字符串的URL中获取域名,这种方法确实很好用。 - nerdherd

5

现在是2013年,我找到的解决方案很简单:

System.out.println(InternetDomainName.fromLenient(uriHost).topPrivateDomain().name());

3
这很简单:
  try {
        String domainName = new URL("http://www.zoyanailpolish.blogspot.com/some/long/link").getHost();

        String[] levels = domainName.split("\\.");
        if (levels.length > 1)
        {
            domainName = levels[levels.length - 2] + "." + levels[levels.length - 1];
        }

        // now value of domainName variable is blogspot.com
    } catch (Exception e) {}

1
发生了什么事: www.zoyanailpolish.blogspot.co.uk - Clive Paterson

2

正如BalusC和其他人建议的那样,最实用的解决方案是获取TLD列表(请参见此列表),将它们保存到文件中,加载它们,然后确定正在使用给定url字符串的TLD。从那里开始,您可以构成以下主域名:

    String url = "zoyanailpolish.blogspot.com";

    String tld = findTLD( url ); // To be implemented. Add to helper class ?

    url = url.replace( "." + tld,"");  

    int pos = url.lastIndexOf('.');

    String mainDomain = "";

    if (pos > 0 && pos < url.length() - 1) {
        mainDomain = url.substring(pos + 1) + "." + tld;
    }
    // else: Main domain name comes out empty

实现细节由您决定。

给@James Poulson,谢谢。抱歉,你的示例输出是什么?我不太明白。它首先删除tld,然后再添加它。那么最终的输出是什么? - chnet
这是伪代码,因此没有输出。需要创建一个列出TLD的文本文件(可以在维基百科链接中找到TLD),将其读入数据结构并填写findTLD方法。如果正确完成,则应该实现您想要的功能,即返回blogspot.com。 - James P.
对@James Poulson,没错。假设我得到了tld,伪例子将从url中删除“.com”。然后,它移动到“blogspot”之前的点位置。通过这种方式,您可以删除“zoyanailpolish”。 - chnet
那就是我们的想法 :)。如果您在实现过程中遇到任何问题,请告诉我。 - James P.
1
也许这不再是一个好主意了,因为未来几年会有成千上万个新的顶级域名。 - andreas

1
你看到 zoyanailpolish.blogspot.com 的原因是你的正则表达式只匹配以 'ww' 开头的字符串。你想要的是除了删除所有以 'ww' 开头的字符串外,还应该适用于以 'zoyanailpolish' 开头的字符串。在这种情况下,使用正则表达式 String regex = "^((ww|z|a)[a-zA-Z0-9-]{0,}\\.)"; 这将删除任何以 'ww'、'z' 或 'a' 开头的单词。根据你的需要进行自定义。

正确。除了删除所有以“ww”开头的字符串之外,它还应该适用于以其他字符开头的字符串(不仅限于“zoyanailpolish”)。例如,“xyz.blogspot.com”。 - chnet
1
但是,正如您展示的那样,对于 xtop10.net 它并没有移除 xtop10 - 这意味着对于某些字符串它不会移除 - 对吗?问题是 - 您是想要一个自定义的字符串列表不被移除还是有一条规则来控制这个过程? - Bhaskar
1
@James 是吗?那他应该这么说啊,对不对?我希望他可以开心地告诉别人,".com"、".co.uk"和"pvt.k12.wy.us"都算是同一种东西。 - tchrist
@chnet:说实话,如果你担心获取域名,那么在我看来使用正则表达式并不是正确的方法。Java中有其他技术可以解析URL并提取域名。 - Bhaskar
@tchrist:在问题下面的第九条评论。我猜测从最后一个URL字符串中需要什么。正则表达式很可能需要一个可怕的表达式来解决所有可能性,因此已经发布了替代方案。 - James P.
显示剩余2条评论

1

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