web-dev-qa-db-fra.com

Extraire les URL du texte en PHP

J'ai ce texte:

$string = "this is my friend's website http://example.com I think it is coll";

Comment puis-je extraire le lien dans une autre variable?

Je sais que cela devrait se faire en utilisant une expression régulière en particulier preg_match() mais je ne sais pas comment?

38
ahmed

Le moyen le plus sûr consiste probablement à utiliser des extraits de code provenant de WordPress. Téléchargez le dernier (actuellement 3.1.1) et voyez wp-includes/formating.php. Il y a une fonction nommée make_clickable qui a du texte brut pour param et qui retourne une chaîne formatée. Vous pouvez récupérer des codes pour extraire des URL. C'est assez complexe cependant.

Cette expression régulière en ligne pourrait être utile.

preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $string, $match);

Mais cette expression rationnelle ne peut toujours pas supprimer certaines URL malformées (ex. http://google:ha.ckers.org).

Voir aussi: Comment imiter le comportement de liaison automatique de StackOverflow

45
Nobu

J'ai essayé de faire ce que Nobu avait dit, en utilisant Wordpress, mais à cause de nombreuses dépendances avec d'autres fonctions WordPress, j'ai plutôt choisi d'utiliser l'expression régulière de Nobu pour preg_match_all() et de la transformer en une fonction utilisant preg_replace_callback() ; une fonction qui remplace désormais tous les liens d'un texte par des liens cliquables. Il utilise fonctions anonymes donc vous aurez besoin de PHP 5.3 ou vous pouvez réécrire le code pour utiliser une fonction ordinaire à la place.

<?php 

/**
 * Make clickable links from URLs in text.
 */

function make_clickable($text) {
    $regex = '#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#';
    return preg_replace_callback($regex, function ($matches) {
        return "<a href=\'{$matches[0]}\'>{$matches[0]}</a>";
    }, $text);
}
15
Mikael Roos

Les URL ont un assez définition complexe - vous devez d'abord choisir ce que vous voulez capturer. Un exemple simple capturant tout ce qui commence par http:// et https:// pourrait être:

preg_match_all('!https?://\S+!', $string, $matches);
$all_urls = $matches[0];

Notez que ceci est très basique et pourrait capturer des URL non valides. Je recommanderais de rattraper POSIX et PHP expressions régulières pour des choses plus complexes.

10
soulmerge

Si le texte à partir duquel vous extrayez les URL est soumis par l'utilisateur et que vous allez afficher le résultat sous la forme de liens, vous devez être très, TRÈS prudent pour éviter les vulnérabilités XSS , plus clairement "javascript:" URL de protocole , mais aussi URL malformées qui pourraient amener votre regexp et/ou le navigateur qui l'affiche à les exécuter en tant qu'URL Javascript. À tout le moins, vous ne devez accepter que les URL commençant par "http", "https" ou "ftp".

Il y a aussi une entrée blog de Jeff où il décrit d'autres problèmes d'extraction d'URL.

8

Le code qui a fonctionné pour moi (surtout si vous avez plusieurs liens dans votre chaîne $) est le suivant: 

$string = "this is my friend's website http://example.com I think it is cool, but this is cooler http://www.memelpower.com :)";
$regex = '/\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i';
preg_match_all($regex, $string, $matches);
$urls = $matches[0];
// go over all links
foreach($urls as $url) 
{
    echo $url.'<br />';
}

J'espère que cela aide les autres aussi.

5
Kai Noack

Vous pourriez faire comme ça ..

<?php
$string = "this is my friend's website http://example.com I think it is coll";
echo explode(' ',strstr($string,'http://'))[0]; //"prints" http://example.com
5
Shankar Damodaran
preg_match_all('/[a-z]+:\/\/\S+/', $string, $matches);

C'est un moyen facile qui fonctionnerait pour beaucoup de cas, pas tous. Tous les matchs sont mis en $ matchs. Notez que cela ne couvre pas les liens dans les éléments d'ancrage (<a href = "" ...), mais ce n'était pas dans votre exemple non plus.

4
runfalk
preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+".
                "(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/",
                $var, &$matches);

$matches = $matches[1];
$list = array();

foreach($matches as $var)
{    
    print($var."<br>");
}
2
user923477

Vous pouvez essayer ceci pour trouver le lien et réviser le lien (ajoutez le lien href).

$reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";

// The Text you want to filter for urls
$text = "The text you want to filter goes here. http://example.com";

if(preg_match($reg_exUrl, $text, $url)) {

       echo preg_replace($reg_exUrl, "<a href="{$url[0]}">{$url[0]}</a> ", $text);

} else {

       echo "No url in the text";

}

se référer ici: http://php.net/manual/en/function.preg-match.php

1
HTML5 developer
public function find_links($post_content){
    $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
    // Check if there is a url in the text
    if(preg_match_all($reg_exUrl, $post_content, $urls)) {
        // make the urls hyper links,
        foreach($urls[0] as $url){
            $post_content = str_replace($url, '<a href="'.$url.'" rel="nofollow"> LINK </a>', $post_content);
        }
        //var_dump($post_content);die(); //uncomment to see result
        //return text with hyper links
        return $post_content;
    } else {
        // if no urls in the text just return the text
        return $post_content; 
    }
}
0
karolkarp

Cette regex fonctionne très bien pour moi et j'ai vérifié avec tous les types d'URL,

<?php
$string = "Thisregexfindurlhttp://www.rubular.com/r/bFHobduQ3n mixedwithstring";
preg_match_all('/(https?|ssh|ftp):\/\/[^\s"]+/', $string, $url);
$all_url = $url[0]; // Returns Array Of all Found URL's
$one_url = $url[0][0]; // Gives the First URL in Array of URL's
?>

Vérifié avec beaucoup d'URL peuvent trouver ici http://www.rubular.com/r/bFHobduQ3n

0
Vignesh Chinnaiyan