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 :

Supprimer un lien précis dans une chaine [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut Supprimer un lien précis dans une chaine
    Bonjour à Tous,

    Décidément les regex...c'est pas mon fort.
    Soit une chaine :

    aaaaaaaaaaaaaaaa bbbbbbbbbbbbb ccccccccccccc <a href="www.toto.com">chez toto</a> ddddddddddddddddddddddddd eeeeeeeeeeee <a href="www.tata.com">chez tata</a> eeeeeeeeee ffff
    je voudrais supprimer le lien qui contient "tata" dans le href. Quand je dis supprimer, c'est virer toutes balises et attributs pour ne laisser que "chez tata".
    Et bien sûr, le lien "toto" ne doit pas bouger...

  2. #2
    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
    Est-ce que "tata" est dans le nom de domaine comme dans ton exemple ou est-il ailleurs dans la réalité? En d'autres termes, s'agit-il d'exclure un nom de domaine précis? Ou encore, s'agit-il de ne conserver que les liens du domaine "toto"?
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  3. #3
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut
    Bonsoir, en fait je cherche à faire en sorte de pouvoir chercher n'importe quel mot-clé dans le lien et à le virer si le mot clé matche.
    J'ai bricolé ça, mais évidemment ça dégage tous les liens quand ça matche.
    J'arrive aussi à virer le href le title, mais il reste des balises, des apostrophes...bref pas net.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    function nettoie_chaine_lien($texte){
    	$dom = new DOMDocument;
    	$dom->loadHTML($texte);
    	foreach ($dom->getElementsByTagName('a') as $node) {
    		if(strpos($node->getAttribute( 'href' ), "images/") !== false || strpos($node->getAttribute( 'href' ), "tata.com") !== false){
    			$texte = preg_replace('#<a href=(.*)>(.*)</a>#siU','',$texte);
    		}
    	}
    	return $texte;
    }

  4. #4
    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
    Tu peux faire un truc intéressant en utilisant XPath qui te permet des sélections assez précises, exemple:
    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
    $keyword='pouet-pouet';
     
    $dom = new DOMDocument;
    libxml_use_internal_errors(true);
    $dom->loadHTML($tonHTML, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NO_IMPLIED);
    $xp = new DOMXPath($dom);
     
    // on ne sélectionne que les nœuds lien dont l'attribut href contient le mot-clef
    $linksToRemove = $xp->query('//a[contains(@href, "'. $keyword .'")]');
     
    foreach($linksToRemove as $link) {
        // on crée un fragment pour y copier tous les nœuds enfants du nœud lien 
        $fragment = $dom->createDocumentFragment();
        foreach ($link->childNodes as $childNode) {
            $fragment->appendChild($childNode->cloneNode(true));
        }
        // pour pouvoir ensuite remplacer le nœud lien par le fragment.
        $link->parentNode->replaceChild($fragment, $link);
    }
     
    echo $dom->saveHTML();
     
    libxml_clear_errors();

    NB: si tu travailles sur des "morceaux" de Html et pas sur un document complet (avec un élément racine "html"), pour éviter que libxml ajoute artificiellement un élément racine comme <p>...</p> autour du code html, tu dois prendre les devants en ajoutant toi-même un élément racine, et en extrayant tous les nœuds enfant de cette racine pour obtenir le résultat voulu. Il faut donc remplacer le chargement du document par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $dom->loadHTML('<div id="root">' . $tonHTML . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    et afficher le résultat avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    foreach ($dom->getElementById('root')->childNodes as $child) {
        echo $dom->saveHTML($child);
    }
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    un pattern qui semble fonctionner (?*) :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <?php
    $texte = 'aaaaa <b>bbbb</b> ccccc <a href="www.toto.com/blabla.php">chez toto</a> dddddddddd <a href="www.titi.com">chez titi</a> fffffffff <a href="www.tata.com">chez tata</a> eeeeeeeeee ffff ';

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function nettoie_chaine_lien_preserve_content($texte, $href_to_suppr_array){
    	$href_to_suppr_all = implode( '|', $href_to_suppr_array);
    	$pattern = '#<a([^>])href=\"('.$href_to_suppr_all.')([^>]*)\"([^>]*)>(.*)<\/a>#Ui';
    	$texte = preg_replace($pattern,'$5',$texte);
    	return $texte;
    }

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $texte_nettoye = nettoie_chaine_lien_preserve_content( $texte, array('www.toto.com','www.tata.com') );
    echo '<pre>'; print_r($texte_nettoye); echo '</pre>';
    ?>

    Renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    aaaaa <b>bbbb</b> ccccc chez toto dddddddddd <a href="www.titi.com">chez titi</a> fffffffff chez tata eeeeeeeeee ffff
    N.B. Mais je ne suis très loind d'être un spécialiste, comme KnackyHertaFromOuterSpace.
    * (au moins 1h que je me casse la tête dessus... et juste par curiosité personnelle" !)

  6. #6
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut
    A CosmoKnacki : wouaaaaaaaaawwwwwwwwwwwwwww !!!!!!!

    Ah ouais...quand même...
    C'est stratosphérique et ça fonctionne nickel !
    Merci beaucoup !

    PS : une question toutefois. A l'affichage le UTF-8 est un peu massacré. Qu'en est-il si j'insère tout ça dans la BDD ?

  7. #7
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut
    A Jreaux62 : merci à toi d'avoir passé du temps sur ce petit casse-tête. Une heure ? Il m'aurait fallu un mois !
    Ca fonctionne impec mais, contrairement à la proposition de CosmoKnacki (effectivement outer space ), ton regexp exige d'être précis quant aux mots-clefs.
    Si je cherche "blablabla", le lien ne saute pas, bien que le href contienne le mot-clé.
    Mais c'est déjà très bien.

  8. #8
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut
    Bonjour à CosmoKnacki,

    J'ai crée une fonction à partir de ton code, mais en tentant de passer un array de mots-clés au lieu d'une chaine $keywords :

    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
     
    function nettoie_chaine_lien($texte){
    	$dom = new DOMDocument;
    	libxml_use_internal_errors(true);
    	//$dom->loadHTML($tonHTML, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NO_IMPLIED);
    	$dom->loadHTML('<div id="root">' . $texte . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    	$xp = new DOMXPath($dom);
    	$keywords = array("toto.com","tata.com"); 
    	// on ne sélectionne que les nœuds lien dont l'attribut href contient le mot-clef
    	foreach($keywords as $keyword){
    		$linksToRemove = $xp->query('//a[contains(@href, "'. $keyword .'")]');
    	}
     
    	foreach($linksToRemove as $link) {
    		// on crée un fragment pour y copier tous les nœuds enfants du nœud lien 
    		$fragment = $dom->createDocumentFragment();
    		foreach ($link->childNodes as $childNode) {
    			$fragment->appendChild($childNode->cloneNode(true));
    		}
    		// pour pouvoir ensuite remplacer le nœud lien par le fragment.
    		$link->parentNode->replaceChild($fragment, $link);
    	}
     
    	libxml_clear_errors();
    	return $dom->saveHTML();
    }
    Mais du coup ça ne fonctionne plus.
    J'ai parcouru la doc domXPATH mais je n'ai rien vu de particulier sur le fait de passer par un tableau.
    Si tu passes par là...

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par renaud26 Voir le message
    Bonjour à CosmoKnacki,...
    Bonjour non plus, alors.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    	$pattern = '#<a([^>]*)href=\"([^>]*)('.implode( '|', $href_to_suppr_array).')([^>]*)\"([^>]*)>(.*)<\/a>#Ui';
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    $texte = '<p>aaaaa <b>bbbb</b> ccccc <a href="www.toto.com/blabla.php" title="tortor">chez toto</a>.</p>
    <p>dddddddddd <a href="www.titi.com">chez titi</a>, <em>fffffffff <a title="tartar" href="http://www.tata.com">chez tata</a> eeeeeeeeee</em> ffff.</p>';
     
    function nettoie_chaine_lien_preserve_content($texte, $href_to_suppr_array){
    	$pattern = '#<a([^>]*)href=\"([^>]*)('.implode( '|', $href_to_suppr_array).')([^>]*)\"([^>]*)>(.*)<\/a>#Ui';
    	return preg_replace($pattern,'$6',$texte);
    }
     
    $texte_nettoye = nettoie_chaine_lien_preserve_content( $texte, array('blabla','tata.com') );
    echo $texte_nettoye;
    ?>

    Donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <p>aaaaa <b>bbbb</b> ccccc chez toto.</p>
    <p>dddddddddd <a href="www.titi.com">chez titi</a>, <em>fffffffff chez tata eeeeeeeeee</em> ffff.</p>

  10. #10
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut
    Bonjour non plus, alors.

    Bonjour !
    Loin de moi l'idée d'être impoli, c'est juste parce que mon post s'adressait particulièrement à lui: il parlait de sa suggestion.
    Merci pour ton aide et ta proposition que je m'empresse de tester. Je reviens !

  11. #11
    Membre averti Avatar de renaud26
    Homme Profil pro
    Webmaster
    Inscrit en
    Mars 2003
    Messages
    1 365
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Webmaster

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 365
    Points : 436
    Points
    436
    Par défaut
    Extra ! Ça fonctionne parfaitement et c'est très exactement ce dont j'avais besoin.
    Je te remercie beaucoup pour ton aide précieuse.
    Bon week-end.

  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
    Dans ta fonction tu as écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    foreach($keywords as $keyword){
        $linksToRemove = $xp->query('//a[contains(@href, "'. $keyword .'")]');
    }
    Donc fatalement à chaque tour de boucle, l'ancienne valeur de $linksToRemove est écrasée par la nouvelle et seule les nœuds avec le dernier mot-clef seront traités dans la suite du code.

    Attention si tu ajoutes artificiellement un élément racine <div id="root">...</div>, pour récupérer le résultat tu dois concaténer les chaînes de tous les nœuds enfants de cette élément racine (pour ne plus l'avoir dans le résultat), soit dans la fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $result = '';
    foreach($dom->getElementById('root')->childNodes as $childNode) {
        $result .= $dom->saveHTML($childNode);
    }
    return $result;
    Si tu veux rechercher plusieurs mots-clefs, tu peux le faire en modifiant le prédicat de la requête XPath:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $linksToRemove = $xp->query('//a[contains(@href, "mot-clef1") or contains(@href, "mot-clef2") or ... or contains(@href, "mot-clefn")]';
    Il suffit de générer dynamiquement la requête XPath:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $keywords = ['mot-clef1', 'mot-clef2', 'mot-clef3'];
    $query = '//a[contains(@href, "' . implode('") or contains(@href, "', $keywords) . '")]';
    $linksToRemove = $xp->query($query);
    Pour ce qui est du problème d'encodage, il suffit de le préciser en même temps que tu ajoutes l'élément racine avec une balise meta:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $dom->loadHTML('<meta charset="UTF-8"/><div id="root">' . $texte . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Supprimer les lettres seules dans une chaine
    Par dguina dans le forum SQL
    Réponses: 2
    Dernier message: 16/04/2013, 15h22
  2. [RegExp] recherche d'un mot précis dans une chaine
    Par oceane751 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 06/04/2012, 11h23
  3. Supprimer le 4eme caractère dans une chaine
    Par xyrox dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 13/07/2011, 07h43
  4. [WD14] ouvrir un lien html dans une chaine
    Par TELKA dans le forum WinDev
    Réponses: 3
    Dernier message: 17/03/2011, 19h45
  5. Réponses: 2
    Dernier message: 12/01/2004, 13h56

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