Регулярное выражение для получения domain.tld - PullRequest
4 голосов
/ 14 мая 2009

Мне нужно регулярное выражение в Java, которое я могу использовать для получения части domain.tld из любого URL. Так что https://foo.com/bar, http://www.foo.com # bar , http://bar.foo.com все вернет foo.com.

Я написал это регулярное выражение, но оно соответствует целому URL

Pattern.compile("[.]?.*[.x][a-z]{2,3}");

Я не уверен, что соответствую "." характер прав. Я старался "." но я получаю сообщение об ошибке от netbeans.

Обновление:

Время не ограничено 2 или 3 символами, и http://www.foo.co.uk/bar должно возвращать foo.co.uk.

Ответы [ 8 ]

10 голосов
/ 14 мая 2009

Это сложнее, чем вы можете себе представить. Ваш пример https://foo.com/bar, содержит запятую, которая является допустимым символом URL. Вот отличный пост о некоторых неприятностях:

https://blog.codinghorror.com/the-problem-with-urls/

https?://([-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|])

Хорошая отправная точка

Некоторые списки из «Освоения регулярных выражений» на эту тему:

http://regex.info/listing.cgi?ed=3&p=207

@ sjobe

>>> import re
>>> pattern = r'https?://([-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|])'
>>> url = re.compile(pattern)
>>> url.match('http://news.google.com/').groups()
('news.google.com/',)
>>> url.match('not a url').groups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'
>>> url.match('http://google.com/').groups()
('google.com/',)
>>> url.match('http://google.com').groups()
('google.com',)

извините, пример на python, а не на java, это более кратко. Java требует некоторого постороннего экранирования регулярного выражения.

8 голосов
/ 14 мая 2009

Я бы использовал класс java.net.URI для извлечения имени хоста, а затем использовал бы регулярное выражение для извлечения последних двух частей uri хоста.

import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RunIt {

    public static void main(String[] args) throws URISyntaxException {
        Pattern p = Pattern.compile(".*?([^.]+\\.[^.]+)");

        String[] urls = new String[] {
                "https://foo.com/bar",
                "http://www.foo.com#bar",
                "http://bar.foo.com"
        };

        for (String url:urls) {
            URI uri = new URI(url);
            //eg: uri.getHost() will return "www.foo.com"
            Matcher m = p.matcher(uri.getHost());
            if (m.matches()) {
                System.out.println(m.group(1));
            }
        }
    }
}

Печать:

foo.com
foo.com
foo.com
7 голосов
/ 14 мая 2009

Если строка содержит действительный URL-адрес, вы можете использовать регулярное выражение типа (цитирование Perl):

/^
(?:\w+:\/\/)?
[^:?#\/\s]*?

(
[^.\s]+
\.(?:[a-z]{2,}|co\.uk|org\.uk|ac\.uk|org\.au|com\.au|___etc___)
)

(?:[:?#\/]|$)
/xi;

Результаты:

url: https://foo.com/bar
matched: foo.com
url: http://www.foo.com#bar
matched: foo.com
url: http://bar.foo.com
matched: foo.com
url: ftp://foo.com
matched: foo.com
url: ftp://www.foo.co.uk?bar
matched: foo.co.uk
url: ftp://www.foo.co.uk:8080/bar
matched: foo.co.uk

Для Java это будет что-то вроде:

"^(?:\\w+://)?[^:?#/\\s]*?([^.\\s]+\\.(?:[a-z]{2,}|co\\.uk|org\\.uk|ac\\.uk|org\\.au|com\\.au|___etc___))(?:[:?#/]|$)"

Конечно, вам нужно заменить и т. Д. .

Пример сценария Perl:

use strict;

my @test = qw(
    https://foo.com/bar
    http://www.foo.com#bar
    http://bar.foo.com
    ftp://foo.com
    ftp://www.foo.co.uk?bar
    ftp://www.foo.co.uk:8080/bar
);

for(@test){
    print "url: $_\n";

    /^
    (?:\w+:\/\/)?
    [^:?#\/\s]*?

    (
    [^.\s]+
    \.(?:[a-z]{2,}|co\.uk|org\.uk|ac\.uk|org\.au|com\.au|___etc___)
    )

    (?:[:?#\/]|$)
    /xi;

    print "matched: $1\n";
}
4 голосов
/ 09 ноября 2011

new URL(url).getHost()

Регулярное выражение не требуется.

3 голосов
/ 14 мая 2009

Вам нужно будет получить список всех возможных TLD и ccTLD, а затем сопоставить их. Вы должны сделать это, иначе вы никогда не сможете различить subdomain.dom.com и hello.co.uk.

Итак, возьми себе такой список. Я рекомендую перевернуть его, чтобы вы хранили, например, uk.co. Затем вы можете извлечь домен из URL, получая все между // и / или концом строки. Разделить на. и работать в обратном направлении, сопоставляя TLD и затем 1 дополнительный уровень, чтобы получить домен.

0 голосов
/ 08 сентября 2016

Код:

public class DomainUrlUtils {
    private static String[] TLD = {"com", "net"}; // top-level domain
    private static String[] SLD = {"co\\.kr"}; // second-level domain

    public static String getDomainName(String url) {
        Pattern pattern = Pattern.compile("(?<=)[^(\\.|\\/)]\\w+\\.(" + joinTldAndSld("|") + ")$");
        Matcher match = pattern.matcher(url);
        String domain = null;

        if (match.find()) {
            domain = match.group();
        }

        return domain;
    }

    private static String joinTldAndSld(String delimiter) {
        String t = String.join(delimiter, TLD);
        String s = String.join(delimiter, SLD);

        return new StringBuilder(t).append(s.isEmpty() ? "" : "|" + s).toString();
    }
}

Тест:

public class DomainUrlUtilsTest {

    @Test
    public void getDomainName() throws Exception {
        // given
        String[][] domainUrls = {
            {
                "test.com",
                "sub1.test.com",
                "sub1.sub2.test.com",
                "https://sub1.test.com",
                "http://sub1.sub2.test.com"
            },
            {
                "https://domain.com",
                "https://sub.domain.com"
            },
            {
                "http://domain.co.kr",
                "http://sub.domain.co.kr",
                "http://local.sub.domain.co.kr",
                "http://local-test.sub.domain.co.kr",
                "sub.domain.co.kr",
                "domain.co.kr",
                "test.sub.domain.co.kr"
            }
        };

        String[] expectedUrls = {
            "test.com",
            "domain.com",
            "domain.co.kr"
        };

        // when
        // then
        for (int domainIndex = 0; domainIndex < domainUrls.length; domainIndex++) {
            for (String url : domainUrls[domainIndex]) {
                String convertedUrl = DomainUrlUtils.getDomainName(url);

                if (expectedUrls[domainIndex].equals(convertedUrl)) {
                    System.out.println(url + " -> " + convertedUrl);
                } else {
                    Assert.fail("origin Url: " + url + " / converted Url: " + convertedUrl);
                }
            }
        }
    }
}

Результаты:

test.com -> test.com
sub1.test.com -> test.com
sub1.sub2.test.com -> test.com
https://sub1.test.com -> test.com
http://sub1.sub2.test.com -> test.com
https://domain.com -> domain.com
https://sub.domain.com -> domain.com
http://domain.co.kr -> domain.co.kr
http://sub.domain.co.kr -> domain.co.kr
http://local.sub.domain.co.kr -> domain.co.kr
http://local-test.sub.domain.co.kr -> domain.co.kr
sub.domain.co.kr -> domain.co.kr
0 голосов
/ 06 июля 2016

Это работает для меня:

public static String getDomain(String url){
    if(TextUtils.isEmpty(url)) return null;
    String domain = null;
    if(url.startsWith("http://")) {
        url = url.replace("http://", "").trim();
    } else if(url.startsWith("https://")) {
        url = url.replace("https://", "").trim();
    }
    String[] temp = url.split("/");
    if(temp != null && temp.length > 0) {
        domain = temp[0];
    }  
    return domain;
}
0 голосов
/ 15 октября 2015
    /[^.]*\.[^.]{2,3}(?:\.[^.]{2,3})?$/

Почти там, но не будет совпадать, когда домен второго уровня содержит 3 символа, подобных этому: www.foo.com Проверьте это здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...