web-dev-qa-db-fra.com

Détecter et extraire l'URL d'une chaîne?

C'est une question facile, mais je ne comprends tout simplement pas… .. Je veux détecter l'URL d'une chaîne et la remplacer par une autre.

J'ai trouvé cette expression de stackoverflow, mais le résultat est simplement 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;

Y a-t-il une meilleure idée?

32
Shisoft

m.group (1) vous donne le premier groupe correspondant, c'est-à-dire la première parenthèse de capture. Ici c'est (https?|ftp|file)

Vous devriez essayer de voir s'il y a quelque chose dans m.group (0) ou entourez tout votre motif de parenthèses et utilisez à nouveau m.group (1).

Vous devez répéter votre fonction de recherche pour correspondre à la suivante et utiliser le nouveau tableau de groupe.

7
M'vy

Permettez-moi de commencer par dire que je ne suis pas un ardent défenseur de la regex pour les cas complexes. Essayer d'écrire l'expression parfaite pour quelque chose comme cela est très difficile. Cela dit , il m'arrive d'en avoir un pour détecter les URL et il est soutenu par une classe de cas de test d'unité de 350 lignes qui passe. Quelqu'un a commencé avec une simple expression rationnelle et au fil des ans, nous avons développé l'expression et les scénarios de test pour traiter les problèmes que nous avons rencontrés. Ce n'est certainement pas trivial:

// 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}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);

Voici un exemple d'utilisation:

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
}
78
WhiteFang34
/**
 * 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;
}

Exemple:

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);
}

Impressions:

https://stackoverflow.com/
http://www.google.com/
31
BullyWiiPlaza

Détecter les URL n'est pas une tâche facile. Si cela vous suffit pour obtenir une chaîne commençant par https? | Ftp | fichier, alors tout ira bien. Votre problème ici est que vous avez un groupe de capture, le () et ceux-ci ne sont que autour de la première partie http ...

Je voudrais faire de cette partie un groupe sans capture en utilisant (? :) et mettre des crochets autour du tout.

"\\b((?:https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])"
2
stema

Avec quelques crochets supplémentaires autour du tout (sauf la limite de mot au début), il devrait correspondre au nom de domaine entier:

"\\b((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])"

Je ne pense pas que cette expression rationnelle corresponde à l'URL complète.

2
Billy Moon

Ce petit fragment de code/fonction extraira efficacement les chaînes d’URL d’une chaîne en Java. J'ai trouvé la regex de base pour le faire ici, et je l'ai utilisé dans une fonction Java.

J'ai développé un peu la regex de base avec la partie “| www [.]” Afin d'attraper des liens ne commençant pas par “http: //”

Assez parlé (c’est bon marché), voici le code:

//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+&amp;@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&amp;@#/%=~_()|]";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);
while(m.find()) {
String urlStr = m.group();
if (urlStr.startsWith("(") &amp;&amp; urlStr.endsWith(")"))
{
urlStr = urlStr.substring(1, urlStr.length() - 1);
}
links.add(urlStr);
}
return links;
}
0
lemmy njaria