问题

给定一个URL,我想提取域名(它不应该包含'www'部分)。网址可以包含h​​ttp / https。这是我写的java代码。虽然它似乎工作正常,有没有更好的方法或有一些边缘情况,可能会失败。

public static String getDomainName(String url) throws MalformedURLException{
    if(!url.startsWith("http") && !url.startsWith("https")){
         url = "http://" + url;
    }        
    URL netUrl = new URL(url);
    String host = netUrl.getHost();
    if(host.startsWith("www")){
        host = host.substring("www".length()+1);
    }
    return host;
}

输入:http://google.com/blah

输出:google.com


#1 热门回答(223 赞)

如果要解析URL,请使用java.net.URI.java.net.URL存在一系列问题 - 它的DNS查找意味着使用它的代码在与不受信任的输入一起使用时可能容易受到拒绝服务攻击。

"Mr. Gosling -- why did you make url equals suck?"解释了一个这样的问题。养成使用java.net.URI的习惯。

public static String getDomainName(String url) throws URISyntaxException {
    URI uri = new URI(url);
    String domain = uri.getHost();
    return domain.startsWith("www.") ? domain.substring(4) : domain;
}

应该做你想做的事。

虽然它似乎工作正常,有没有更好的方法或有一些边缘情况,可能会失败。

你编写的代码无法使用有效的URL:

  • httpfoo / bar - 具有以http开头的路径组件的相对URL。
  • HTTP://example.com/ - 协议不区分大小写。
    --//example.com/ - 与主机相关的协议相对URL
  • www / foo - 具有以www开头的路径组件的相对URL
  • wwwexample.com - 不以www开头的域名。但是从www开始。

分层URL具有复杂的语法。如果你试图在没有仔细阅读RFC 3986的情况下推出自己的解析器,你可能会弄错它。只需使用内置于核心库中的那个。

如果你真的需要处理java.net.URI所述的混乱输入,请参阅RFC 3986附录B:

附录B.使用正则表达式解析URI引用由于"first-match-wins"算法与POSIX正则表达式使用的"贪婪"消歧方法相同,因此使用正则表达式解析URI引用的潜在五个组件。以下行是用于将格式正确的URI引用分解为其组件的正则表达式。 ^(([^:/?#]):)?(//([^/?#] *))?([^?#] *)(\?([^#] ))?(# (。))?
   12 3 4 5 6 7 8 9
 上面第二行中的数字只是为了提高可读性;它们表示每个子表达的参考点(即每个配对的括号)。


#2 热门回答(61 赞)

import java.net.*;
import java.io.*;

public class ParseURL {
  public static void main(String[] args) throws Exception {

    URL aURL = new URL("http://example.com:80/docs/books/tutorial"
                       + "/index.html?name=networking#DOWNLOADING");

    System.out.println("protocol = " + aURL.getProtocol()); //http
    System.out.println("authority = " + aURL.getAuthority()); //example.com:80
    System.out.println("host = " + aURL.getHost()); //example.com
    System.out.println("port = " + aURL.getPort()); //80
    System.out.println("path = " + aURL.getPath()); //  /docs/books/tutorial/index.html
    System.out.println("query = " + aURL.getQuery()); //name=networking
    System.out.println("filename = " + aURL.getFile()); ///docs/books/tutorial/index.html?name=networking
    System.out.println("ref = " + aURL.getRef()); //DOWNLOADING
  }
}

Read more


#3 热门回答(6 赞)

这是一条简短的线路,使用了247177804in Guava:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()

鉴于http://www.google.com/blah,这将给你google.com。或者,给定http://www.google.co.mx,它会给你google.co.mx

AsSa Qada的评论是another answer on this post,这个问题之前已被提出过:Extract main domain name from a given url。该问题的best answer来自Satya,他建议Guava'sInternetDomainName.topPrivateDomain()

public boolean isTopPrivateDomain()指示此域名是否仅由一个子域组件后跟公共后缀组成。例如,google.com和foo.co.uk返回true,但www.google.com或co.uk不返回true。警告:此方法的真实结果并不意味着域位于可作为主机寻址的最高级别,因为许多公共后缀也是可寻址的主机。例如,域bar.uk.com的公共后缀为uk.com,因此它将从此方法返回true。但是uk.com本身就是一个可寻址的主机。此方法可用于确定域是否可能是可以设置cookie的最高级别,但即使这取决于各个浏览器的cookie控件实现。有关详细信息,请参阅RFC 2109。

将它与原始帖子已包含的URL.getHost()放在一起,可以为你提供:

import com.google.common.net.InternetDomainName;

import java.net.URL;

public class DomainNameMain {

  public static void main(final String... args) throws Exception {
    final String urlString = "http://www.google.com/blah";
    final URL url = new URL(urlString);
    final String host = url.getHost();
    final InternetDomainName name = InternetDomainName.from(host).topPrivateDomain();
    System.out.println(urlString);
    System.out.println(host);
    System.out.println(name);
  }
}

原文链接