IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

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


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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 : 24
    Points
    24
    Par défaut
    Bonjour,

    Voilà une solution à ton problème (si j'ai bien compris):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    Par défaut
    Apparement, j'ai trouvé quelque chose qui a l'air de bien fonctionner

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    preg_replace("|(?!<[^<>]*?)(?<![?./&])\b(motcle)\b(?!:)(?![^<>]*?>)|imsU","<a href=\"\">$1</a>" , $string);

  8. #8
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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é!
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  9. #9
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    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.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  11. #11
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  13. #13
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    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
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    si a<b<c alors c>a (le mot clé est "alors")
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  15. #15
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Pour revenir sur cet ancien sujet, il y avait beaucoup plus simple, en une seule étape:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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);
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

Discussions similaires

  1. [WD-2010] renvoi / liens sur des mots-clefs
    Par Lili120 dans le forum Word
    Réponses: 2
    Dernier message: 06/01/2011, 20h12
  2. [RegEx] Regex pour extension page monitor sur google chrome
    Par Ellodie dans le forum Langage
    Réponses: 0
    Dernier message: 24/06/2010, 17h04
  3. Ajouter des liens sur des mots clefs contenu dans une div
    Par Nementon dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 31/05/2010, 11h32
  4. Problème pour placer le site sur un MAC
    Par Garra dans le forum Flash
    Réponses: 28
    Dernier message: 30/01/2007, 17h31
  5. Formulaire : un lien sur un mot
    Par Jarodd dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 05/06/2006, 16h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo