URLを指定して、ドメイン名を抽出したい(「www」部分を含めるべきではない) URLにはhttp/httpsを含めることができます。これが私が書いたJavaコードです。それはうまくいくようですが、より良いアプローチがありますか、それとも失敗する可能性のあるEdgeのケースがありますか?.
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;
}
出力:google.com
URLを解析する場合は、 Java.net.URI
を使用します。 Java.net.URL
には多くの問題があります。そのequals
メソッドはDNSルックアップを行うため、信頼できない入力で使用すると、それを使用するコードがサービス拒否攻撃に対して脆弱になる可能性があります。
"Mr。Gosling-なぜURLをイコールにするのですか?" はそのような問題の1つを説明しています。代わりに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/
-ホストを含むプロトコル相対URLwww/foo
-www
で始まるパスコンポーネントを持つ相対URLwwwexample.com
-www.
ではなく、www
で始まるドメイン名。階層URLには複雑な文法があります。 RFC 3986を注意深く読まずに独自のパーサーをロールしようとすると、おそらく間違ったものになるでしょう。コアライブラリに組み込まれているものを使用するだけです。
Java.net.URI
が拒否する厄介な入力を本当に処理する必要がある場合は、 RFC 3986 付録Bを参照してください。
付録B.正規表現を使用したURI参照の解析
「first-match-wins」アルゴリズムはPOSIX正規表現で使用される「貪欲な」曖昧性解消方法と同一であるため、URI参照の潜在的な5つのコンポーネントを解析するために正規表現を使用するのが自然でありふれています。
次の行は、整形式URI参照をコンポーネントに分解するための正規表現です。
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? 12 3 4 5 6 7 8 9
上記の2行目の数字は、読みやすくするためのものです。それらは、各部分式(つまり、それぞれの括弧)の参照点を示します。
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
}
}
以下は、グアバでInternetDomainName.topPrivateDomain()
を使用した短くシンプルな行です:InternetDomainName.from(new URL(url).getHost()).topPrivateDomain().toString()
http://www.google.com/blah
を指定すると、google.com
が得られます。または、http://www.google.co.mx
を指定すると、google.co.mx
が提供されます。
Sa Qada で この投稿に関する別の回答 でコメントされているため、この質問は以前に尋ねられました: 特定のURLからメインドメイン名を抽出 。 ベストアンサー その質問に対する回答は Satya で、Guavaの InternetDomainName.topPrivateDomain() を提案しています。
public boolean isTopPrivateDomain()
このドメイン名が、パブリックサフィックスが後に続く1つのサブドメインコンポーネントだけで構成されるかどうかを示します。たとえば、google.comおよびfoo.co.ukに対してtrueを返しますが、www.google.comまたはco.ukに対しては返しません。
警告:多くのパブリックサフィックスもアドレス可能なホストであるため、このメソッドの真の結果は、ドメインがホストとしてアドレス可能な最高レベルであることを意味するものではありません。たとえば、ドメイン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);
}
}
URLのドメイン名を抽出し、単純な文字列照合を使用するメソッド(以下を参照)を作成しました。実際に行うのは、最初の"://"
(または0
が含まれていない場合はインデックス"://"
)と最初の後続の"/"
(または後続の"/"
がない場合はインデックスString.length()
)の間のビットを抽出することです。残りの前の"www(_)*."
ビットは切り取られます。これで十分ではない場合もあると思いますが、ほとんどの場合は十分であるはずです!
上記のMike Samuelの投稿によると、Java.net.URI
クラスでこれを行うことができました(そしてJava.net.URL
クラスよりも好まれました)が、URI
クラスで問題が発生しました。特に、URLにスキーム、つまりURI.getHost()
ビットが含まれていない場合、"http(s)"
はnull値を返します。
/**
* Extracts the domain name from {@code url}
* by means of String manipulation
* rather than using the {@link URI} or {@link URL} class.
*
* @param url is non-null.
* @return the domain name within {@code url}.
*/
public String getUrlDomainName(String url) {
String domainName = new String(url);
int index = domainName.indexOf("://");
if (index != -1) {
// keep everything after the "://"
domainName = domainName.substring(index + 3);
}
index = domainName.indexOf('/');
if (index != -1) {
// keep everything before the '/'
domainName = domainName.substring(0, index);
}
// check for and remove a preceding 'www'
// followed by any sequence of characters (non-greedy)
// followed by a '.'
// from the beginning of the string
domainName = domainName.replaceFirst("^www.*?\\.", "");
return domainName;
}
URIオブジェクトの作成後に小さな処理を行いました
if (url.startsWith("http:/")) {
if (!url.contains("http://")) {
url = url.replaceAll("http:/", "http://");
}
} else {
url = "http://" + url;
}
URI uri = new URI(url);
String domain = uri.getHost();
return domain.startsWith("www.") ? domain.substring(4) : domain;
同様の質問があります 指定されたURLからメインドメイン名を抽出する 。この answer を見ると、非常に簡単であることがわかります。あなただけのJava.net.URL
とString
ユーティリティを使用する必要があります-Split
private static final String hostExtractorRegexString = "(?:https?://)?(?:www\\.)?(.+\\.)(com|au\\.uk|co\\.in|be|in|uk|org\\.in|org|net|edu|gov|mil)";
private static final Pattern hostExtractorRegexPattern = Pattern.compile(hostExtractorRegexString);
public static String getDomainName(String url){
if (url == null) return null;
url = url.trim();
Matcher m = hostExtractorRegexPattern.matcher(url);
if(m.find() && m.groupCount() == 2) {
return m.group(1) + m.group(2);
}
else {
return null;
}
}
説明:正規表現には4つのグループがあります。最初の2つは一致しないグループで、次の2つは一致するグループです。
最初に一致しないグループは「http」または「https」または「」です
2番目の不一致グループは「www」です。または「」
2番目に一致するグループは トップレベルドメイン です
最初に一致するグループは、一致しないグループの後、およびトップレベルドメインの前にあるものです。
一致する2つのグループを連結すると、ドメイン/ホスト名が得られます。
PS:サポートされているドメインをいくつでも正規表現に追加できることに注意してください。
これを試してください:Java.net.URL;
JOptionPane.showMessageDialog(null、getDomainName(new URL( " https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains ")));
public String getDomainName(URL url){
String strDomain;
String[] strhost = url.getHost().split(Pattern.quote("."));
String[] strTLD = {"com","org","net","int","edu","gov","mil","arpa"};
if(Arrays.asList(strTLD).indexOf(strhost[strhost.length-1])>=0)
strDomain = strhost[strhost.length-2]+"."+strhost[strhost.length-1];
else if(strhost.length>2)
strDomain = strhost[strhost.length-3]+"."+strhost[strhost.length-2]+"."+strhost[strhost.length-1];
else
strDomain = strhost[strhost.length-2]+"."+strhost[strhost.length-1];
return strDomain;}
私の場合、私はメインドメインのみを必要とし、サブドメインは必要ありませんでした(「www」などのサブドメインは不要です)。
public static String getUrlDomain(String url) throws URISyntaxException {
URI uri = new URI(url);
String domain = uri.getHost();
String[] domainArray = domain.split("\\.");
if (domainArray.length == 1) {
return domainArray[0];
}
else {
return domainArray[domainArray.length - 2] + "." + domainArray[domainArray.length - 1];
}
}
このメソッドでは、URL「 https://rest.webtoapp.io/llSlider?lg=en&t=8 」はドメイン「webtoapp.io」に対して使用されます。
入力URLがユーザー入力の場合。このメソッドは、最も適切なホスト名を提供します。見つからない場合は、入力URLが返されます。
private String getHostName(String urlInput) {
urlInput = urlInput.toLowerCase();
String hostName=urlInput;
if(!urlInput.equals("")){
if(urlInput.startsWith("http") || urlInput.startsWith("https")){
try{
URL netUrl = new URL(urlInput);
String Host= netUrl.getHost();
if(Host.startsWith("www")){
hostName = Host.substring("www".length()+1);
}else{
hostName=Host;
}
}catch (MalformedURLException e){
hostName=urlInput;
}
}else if(urlInput.startsWith("www")){
hostName=urlInput.substring("www".length()+1);
}
return hostName;
}else{
return "";
}
}
上記はすべて良いです。これは私には本当にシンプルで、理解しやすいように思えます。引用をすみません。 Groovy用にDataCenterというクラス内で作成しました。
static String extractDomainName(String url) {
int start = url.indexOf('://')
if (start < 0) {
start = 0
} else {
start += 3
}
int end = url.indexOf('/', start)
if (end < 0) {
end = url.length()
}
String domainName = url.substring(start, end)
int port = domainName.indexOf(':')
if (port >= 0) {
domainName = domainName.substring(0, port)
}
domainName
}
そして、ここにいくつかのjunit4テストがあります:
@Test
void shouldFindDomainName() {
assert DataCenter.extractDomainName('http://example.com/path/') == 'example.com'
assert DataCenter.extractDomainName('http://subpart.example.com/path/') == 'subpart.example.com'
assert DataCenter.extractDomainName('http://example.com') == 'example.com'
assert DataCenter.extractDomainName('http://example.com:18445/path/') == 'example.com'
assert DataCenter.extractDomainName('example.com/path/') == 'example.com'
assert DataCenter.extractDomainName('example.com') == 'example.com'
}