Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 15 sur 15
  1. #1
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut Regex pour placer un lien sur un mot clé, lui même sans lien

    Hello,

    J'ai un petit soucis depuis quelques temps....

    En effet, je désire faire un regex pour placer un lien sur un mot clé (que je récupère via une requête sql). Jusque là pas de soucis.

    Mon problème, c'est que certains de mes mots clés font déjà partie d'un lien... ce qui me fait donc un code html invalide.

    Mon but est donc de rechercher mon mot clé par rapport à une liste (ça ok), puis de vérifier que ce mot clé ne comporte pas de balise <a devant lui (immédiatement ou pas) sans balise fermante, ni qu'il n'y a pas de balise </a> après sans balise ouvrante. En dautres mots donc, je ne veux pas que mon mot clé soit en plein milieu d'un lien. Ex:

    Code :
    1
    2
    <a .....> Une phrase avec mon mot clé</a>  <--- NON
    <a....> Une phrase</a>avec mon mot clé <a...>ici</a> OUI
    Pour le moment, mon code ressemble à cela:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    class autolink {
     
        public function parse($description) {
     
            //Recuperation de la liste des mots cés
            require_once(config::getPathClasses() . 'service/ServiceLiensDynamique.php');
            $liensDyn = new ServiceLiensDynamique(config::$tableLiensDynamiques);
            $resultLiensDyn = $liensDyn->getLiensDynamiques(config::$siteInt);
     
             //Boucle sur chaque mot clé
            foreach($resultLiensDyn as $resultLiensDyn){
                $lien = config::getAccueil().$resultLiensDyn['lien']; //lien a appliquer
                $nom = $resultLiensDyn['nom'];
     
                $arrayARemplacer[] = $resultLiensDyn['nom'];
                $arrayRemplacement[] = "<strong><a href=\"$lien\" title=\"$nom\">$nom</a></strong>";
            }
     
            $description = str_ireplace($arrayARemplacer, $arrayRemplacement, $description,$count);
     
            //TODO vérifier qu'il n'y a pas de liens déjà présent via une balise </a> 
     
           }
     
    }

    Merci pour votre aide !!

  2. #2
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Personne ne peut m'aider ?

    Pour rappel (et simplification de l'énoncé de mon problème) mon but est de pouvoir créer des liens sur des mots clés qui ne disposeraient pas déjà d'un lien.

    Je me suis cassé la tête toute la journée sur ça, sans réussite... En gros donc, je veux pouvoir dans mon regex récupérer les mots clés désirés qui ne disposeraient pas d'un <a href devant le mot et d'un </a> derrière.

    Merci

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    avril 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : avril 2009
    Messages : 19
    Points : 22
    Points
    22

    Par défaut

    Bonjour,

    Voilà une solution à ton problème (si j'ai bien compris):
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    $string = '<a href="non"> Une phrase avec mon mot cle</a>
    <a href="oui"> Une phrase</a>avec mon mot cle <a...>ici</a>';
     
    $mot_cle = 'mot cle';
    $lien = "lien";
    $pattern = "/([^(?:<a .*?>)]*?)($mot_cle)([^(?:<\/a>)]+)/i";
    $replacement = "<strong><a href=\"$lien\" title=\"$mot_cle\">$mot_cle</a></strong>";
     
    echo $string."\n";
     
    echo "--------------------------------------------\n";
    echo preg_replace($pattern, $replacement, $string);

  4. #4
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Oui, tu as parfaitement compris, et cela semble bien marcher

    Je n'ai jamais été très fort en REGEX, et j'en ai chié sur les exclusions... Lors de mes tests, cela me supprimait carrément des bouts de la chaine...

    En un seul coup, tu as réussi, un grand merci à toi !

  5. #5
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Il subiste quelques petits soucis que je n'avais pas pris en comte (si le mot clé est présent dans une balise <img,...
    Je vais donc travailler dessus et posterai le tout si des fois ça peut servir à d'autres

  6. #6
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Je suis de retour

    Le code marche super sur de simples liens, mais si le mot clé se retrouve dans un alt, dans un <img src, dans un title, ou même dans un url ça ne fonctionne plus.

    J'ai donc essayé de rajouter le img, le alt=" et le title=" sans succès... soit ça me répète un nombre incalculable de fois le mot clé, soit cela me coupe la phrase...

    Mon code actuel est donc le suivant:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    $string = '<a href="non" title="motcle en action"> Une phrase avec motcle</a>.
    <a href="oui" title="oui"> Une phrase</a>     avec motcle   <a href="aucun"> ici</a>.';
     
    $mot_cle = 'motcle ';
    $lien = "http://google.fr";
    /*$pattern = "/([^(?:<a .*?>)]*?)($mot_cle)([^>]+)/i"; */
     
    //$pattern = "/([^(title=>)]*?)[\s]+($mot_cle)[\s]+/i";
    $pattern = "/[\s]*([^(?:<a .*?>)]*?)($mot_cle)([^(?:<\/a>)]+)/i";
     
     
    $replacement = " <strong><a href=\"$lien\" title=\"$mot_cle\">$mot_cle</a></strong> ";
     
    echo "Original: $string.\n";
     
    echo "<br/>Modifié: \n";
    echo preg_replace($pattern, $replacement, $string);
    En l'éxécutant, je me retrouve avec ça:

    Original: <a href="non" title="motcle en action"> Une phrase avec motcle</a>.
    <a href="oui" title="oui"> Une phrase</a> avec motcle <a href="aucun"> ici</a>..
    <br/>Modifié:
    <a href="non" <strong><a href="http://google.fr" title="motcle ">motcle </a></strong> action"> Une phrase avec motcle</a>.
    <a href="oui" title="oui"> Une phrase</a> avec <strong><a href="http://google.fr" title="motcle ">motcle </a></strong> <a href="aucun"> ici</a>.
    J'ai également essayé de rajouter le fait que je veux qu'il y ait un espace de chaque côté de mon clé mais le résultat est très bizarre...
    En effet soit je ne met qu'un seul espace dans ma chaine, et ça ne prend pas, soit j'en place plusieurs, et dans ce cas, mon texte est tronqué

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    $string = '<a href="non" title="motcle en action"> Une phrase avec motcle</a>.
    <a href="oui" title="oui"> Une phrase</a>avec motcle        <a href="aucun"> ici</a>.';
     
    $mot_cle = 'motcle ';
    $lien = "http://google.fr";
    /*$pattern = "/([^(?:<a .*?>)]*?)($mot_cle)([^>]+)/i"; */
     
    //$pattern = "/([^(title=>)]*?)[\s]+($mot_cle)[\s]+/i";
    $pattern = "/[\s]*([^(?:<a .*?>)]*?)[\s]+($mot_cle)[\s]+([^(?:<\/a>)]+)/i";
     
     
    $replacement = " <strong><a href=\"$lien\" title=\"$mot_cle\">$mot_cle</a></strong> ";
     
    echo "Original: $string.\n";
     
    echo "<br/>Modifié: \n";
    echo preg_replace($pattern, $replacement, $string);
    Original: <a href="non" title="motcle en action"> Une phrase avec motcle</a>.
    <a href="oui" title="oui"> Une phrase</a>avec motcle <a href="aucun"> ici</a>..
    <br/>Modifié:
    <a href="non" title="motcle en action"> Une phrase avec motcle</a>.
    <a href="oui" title="oui"> Une phrase</a>a <strong><a href="http://google.fr" title="motcle ">motcle </a></strong> <a href="aucun"> ici</a>.
    Comment se fait-il que mon texte soit tronqué ??

    Bref, j'ai de grosses lacunes

  7. #7
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Apparement, j'ai trouvé quelque chose qui a l'air de bien fonctionner

    Code :
    1
    2
     
    preg_replace("|(?!<[^<>]*?)(?<![?./&])\b(motcle)\b(?!:)(?![^<>]*?>)|imsU","<a href=\"\">$1</a>" , $string);

  8. #8
    Membre confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Inscrit en
    mars 2009
    Messages
    213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : mars 2009
    Messages : 213
    Points : 257
    Points
    257

    Par défaut

    Bonjour,

    Malheureusement cette dernière pattern laisse passer le texte des liens et provoque par conséquent des liens imbriqués, ce qui est mal.

    À défaut de le faire en une seule ligne tu peux séparer ta chaine de départ avec preg_split avec l'option PREG_SPLIT_DELIM_CAPTURE en utilisant comme séparateur les cas de figure à éviter
    (ie:
    • le mot clé est déjà encadré par des balises de lien
    • le mot clé se retrouve dans un attribut de balise)
    ce qui te donne un tableau dans lequel va s'alterner les éléments sans séparateur et le séparateur lui même (capturer grace à l'option).
    Reste plus qu'à effectuer le remplacement du mot clé, le cas échéant, dans les items qui ne sont pas le séparateur (soit un sur deux) et à recoller le tableau.

    Soit:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    $pattern="/(  # parenthèses pour capturer le séparateur
                     <a\s.*<\/a> # on match les liens
                     | # ou
                     <[^>]*\"[^\"]*${motcle}[^\"]*\"[^>]*> # le mot clé dans un attribut
                     )/sxU"; // regex non gloutonne, avec recherche multiligne
     
    // (/x permet d'écrire une regex avec des espaces et des sauts de lignes pour commenter)
     
    $string=" $string"; // on insère un caractère bidon (ici un espace) pour être sûr que les items du tableau à traiter seront sur les indexs pairs.
     
    $tab=preg_split($pattern,$string,-1,PREG_SPLIT_DELIM_CAPTURE);
     
    // on traite
     
    for ($i = 0; $i < count($tab); $i+=2) {
        $tab[$i]=preg_replace("/(\b$motcle\b)/i","<a href=\"\">$1</a>",$tab[$i]);
    }
     
    // on recolle et on enlève le caractère bidon
     
    $string=substr(implode("",$tab),1);
    Maintenant, il est clair que ce problème peut se traiter avec une seule regex, mais bon là ça marche. J'espère pour toi qu'il n'y a pas de javascript dans la page contenant le mot clé!

  9. #9
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Oui, tu as raison, cela me fait des liens imbriqués ! C'est moche, et pas forcément super bien par rapport à ce que je veux faire, mais c'est valide W3C (xhtml trans).

    Je te remercie par avance pour ton code. Je vais essayer cela rapidement. Mais en tout cas, ce serait parfait si ça marche, que sa se fasse en une seule ou deux étapes

  10. #10
    Membre confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Inscrit en
    mars 2009
    Messages
    213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : mars 2009
    Messages : 213
    Points : 257
    Points
    257

    Par défaut

    C'est moche, et pas forcément super bien
    Quel sens du compliment!
    mais c'est valide W3C
    En même temps, c'est du PHP.

    Teste bien.

  11. #11
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    Quand je disais moche, pas super bien, et valide w3C, c'était mon code qui faisait des doubles liens, pas ton code

  12. #12
    Membre confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Inscrit en
    mars 2009
    Messages
    213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : mars 2009
    Messages : 213
    Points : 257
    Points
    257

    Par défaut

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $pattern="/(  # parenthèses pour capturer le séparateur
                <a\s.*<\/a> # on match les liens
                | # ou
                <script.*<\/script> # quelques autres trappes à éviter
                |
                <style.*<\/style>
                |
                <title.*<\/title>
                |                 
                <[^>]*\"[^\"]*${motcle}[^\"]*\"[^>]*> # le mot clé dans un attribut
               )/sxU"; // regex non gloutonne, avec recherche multiligne
    reste aprés les cas particuliers, exemple:

    le mot clef recherché est le mot: class

  13. #13
    Membre régulier
    Inscrit en
    mai 2005
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : mai 2005
    Messages : 359
    Points : 81
    Points
    81

    Par défaut

    J'ai essayé tout à l'heure ton code, cela a l'air de bien fonctionner sur me données de test, ce qui est déjà un bon point

    Sauf cas super exceptionnel, mes mots clés ne seront pas des mots "réservés" utilisés en html. On n'est pas à l'abris, c'est sur, mais en théorie, point de problèmes.
    Ceci dit, en faisant un regex qui interdit que le mot clé soit entre < ... et > on devrait pouvoir s'en sortir non ?

  14. #14
    Membre confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Inscrit en
    mars 2009
    Messages
    213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : mars 2009
    Messages : 213
    Points : 257
    Points
    257

    Par défaut

    si a<b<c alors c>a (le mot clé est "alors")

  15. #15
    Membre confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Inscrit en
    mars 2009
    Messages
    213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : mars 2009
    Messages : 213
    Points : 257
    Points
    257

    Par défaut

    Pour revenir sur cet ancien sujet, il y avait beaucoup plus simple, en une seule étape:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $motclef="motcle";
    $string = <<<LOD
    <a href="non" title="motcle en action"> Une phrase avec $motclef</a>.
    <img src="/path/$motclef.jpg" />
    <!-- $motclef -->
    <span class="abc$motclef">def $motclef ghi</span>
    <span> un{$motclef}contenu dans un autre mot</span>
    <a href="oui" title="oui"> Une phrase</a>avec $motclef        <a href="aucun"> ici</a>.
    LOD;
    // TSE SULOBAID LMTH NI XEGER
    $pattern = "~(?:<(a|script|style|title)\s.*</(?1)>) # matche les liens, script, styles
                |(?:<!--.*-->)                          # matche les commentaires
                |(?:<[^>]+>)                            # matche les balises (et leur intérieur) restantes
                |(\b$motclef\b)                         # matche le mot clef sauf s'il est contenu dans un autre mot
                |(?:.)                                  # matche le reste caractère par caractère
                ~sUx";
    function cbReplace($matches) {
        return (isset($matches[2]))?"<a href=\"\">{$matches[2]}</a>":$matches[0];
    }
    $result = preg_replace_callback($pattern, "cbReplace", $string);
    print_r($result);

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •