Обнаружить и извлечь url из строки?
Это простой вопрос, но я просто не понимаю.
Я хочу обнаружить url в строке и заменить их на сокращение.
Я нашел это выражение из stackoverflow, но результатом является только http
Pattern p = Pattern.compile("\\b(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]",Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(str);
boolean result = m.find();
while (result) {
for (int i = 1; i <= m.groupCount(); i++) {
String url=m.group(i);
str = str.replace(url, shorten(url));
}
result = m.find();
}
return html;
Есть ли лучшая идея?
Ответы
Ответ 1
m.group(1) дает вам первую группу соответствия, то есть первую захватывающую скобку. Здесь он (https?|ftp|file)
Вы должны попытаться увидеть, есть ли что-то в m.group(0), или окружить весь ваш шаблон скобками и снова использовать m.group(1).
Вам нужно повторить функцию поиска, чтобы она соответствовала следующей и использовала новый массив групп.
Ответ 2
Позвольте мне продолжить и предисловие к этому, сказав, что я не большой сторонник регулярного выражения для сложных случаев. Пытаться написать идеальное выражение для чего-то подобного очень сложно. Тем не менее, у меня есть один для обнаружения URL-адреса, и он поддерживается 350-строчным классом класса unit test, который проходит. Кто-то начал с простого регулярного выражения, и за эти годы мы разработали выражения и тестовые примеры для решения проблем, которые мы обнаружили. Это определенно не тривиально:
// Pattern for recognizing a URL, based off RFC 3986
private static final Pattern urlPattern = Pattern.compile(
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
+ "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
+ "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*[email protected]!:/{};']*)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
Вот пример его использования:
Matcher matcher = urlPattern.matcher("foo bar http://example.com baz");
while (matcher.find()) {
int matchStart = matcher.start(1);
int matchEnd = matcher.end();
// now you have the offsets of a URL match
}
Ответ 3
/**
* Returns a list with all links contained in the input
*/
public static List<String> extractUrls(String text)
{
List<String> containedUrls = new ArrayList<String>();
String urlRegex = "((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)";
Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE);
Matcher urlMatcher = pattern.matcher(text);
while (urlMatcher.find())
{
containedUrls.add(text.substring(urlMatcher.start(0),
urlMatcher.end(0)));
}
return containedUrls;
}
Пример:
List<String> extractedUrls = extractUrls("Welcome to https://stackoverflow.com/ and here is another link http://www.google.com/ \n which is a great search engine");
for (String url : extractedUrls)
{
System.out.println(url);
}
Печать
https://stackoverflow.com/
http://www.google.com/
Ответ 4
С некоторыми дополнительными скобками вокруг всего объекта (кроме границы слова при запуске) он должен соответствовать всему доменному имени:
"\\b((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])"
Я не думаю, что регулярное выражение соответствует всему URL-адресу.
Ответ 5
Обнаружение URL-адресов - непростая задача. Если это достаточно для вас, чтобы получить строку, которая начинается с файла https? | Ftp |, тогда это может быть хорошо. Ваша проблема здесь в том, что у вас есть группа захвата, ()
, и это только вокруг первой части http...
Я бы сделал эту часть группой без захвата, используя (?:) и поместив скобки вокруг всего.
"\\b((?:https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])"
Ответ 6
Этот небольшой фрагмент кода/функция будет эффективно извлекать строки URL из строки в Java. Я нашел здесь основное регулярное выражение и использовал его в функции Java.
Я немного расширил базовое регулярное выражение в части "| www [.]", Чтобы ловить ссылки, не начинающиеся с "http://"
Хватит говорить (это дешево), вот код:
//Pull all links from the body for easy retrieval
private ArrayList pullLinks(String text) {
ArrayList links = new ArrayList();
String regex = "\\(?\\b(http://|www[.])[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|]";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);
while(m.find()) {
String urlStr = m.group();
if (urlStr.startsWith("(") && urlStr.endsWith(")"))
{
urlStr = urlStr.substring(1, urlStr.length() - 1);
}
links.add(urlStr);
}
return links;
}