REGEX : enlever liens dans liens

  • Auteur de la discussion Auteur de la discussion 7804j
  • Date de début Date de début
WRInaute discret
Bonjour,

J'ai un sympathique script de remplacements automatiques dans mes articles :

Code:
<?php
//Transforme une chaine en regex insensible aux accents. Exemple : Eléphant donne un truc comme (è|e|é|ê|ë|È|É|Ê|Ë)l(è|e|é|ê|ë|È|É|Ê|Ë)ph(a|à|á|â|ã|ä|å|À|Â|Ä|Á)nt
function regexAccents($chaine) {
   $accent = array('a','à','á','â','ã','ä','å','À','Â','Ä','Á','c','ç','Ç','e','è','é','ê','ë','È','É','Ê','Ë','i','ì','í','î','ï','Ï','Î','Ì','Í','o','ð','ò','ó','ô','õ','ö','Ô','Ö','Ò','Ó','u','ù','ú','û','ü','Ù','۟','Ü','Ú','y','ý','ý','ÿ','Ý');
   $inter = array('%01','%02','%03','%04','%05','%06','%07','%08','%09','%10','%11','%12','%13','%14','%15','%16','%17','%18','%19','%20','%21','%22','%23','%24','%25','%26','%27','%28','%29','%30','%31','%32','%33','%34','%35','%36','%37','%38','%39','%40','%41','%42','%43','%44','%45','%46','%47','%48','%49','%50','%51','%52','%53','%54','%55','%56','%57');
   $regex = array('(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)',
'(c|ç|Ç)','(c|ç|Ç)','(c|ç|Ç)',
'(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)',
'(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)',   '(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)',         '(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)',
'(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)');
   $chaine = str_ireplace($accent, $inter, $chaine);//Etape intermédiaire obligatoire, sinon il va y avoir une imbrication des remplacements quasi-infinie, chaque remplacement créant de nouveaux remplacements à faire.
   $chaine = str_replace($inter, $regex, $chaine);      
   return $chaine;
}

//Remplace automatiquement tout ce qui doit être remplaçé dans un champ texte sur le site (ajout de liens automatiques,...). Long temps de chargement donc à utiliser avec modération
function auto_replace($contenu)
	{
		$requete = mysql_query('SELECT * FROM donjons WHERE dj_actif = 1');
		while ($res = mysql_fetch_array($requete))
		{
			$contenu= preg_replace("#(\b|>)". regexAccents(preg_quote($res['dj_nom'], "#"))."(?![^<]*>)\b#i", '$1<a href="/'.$res['dj_type'].'s/'.caract_spec($res['dj_nom']).'-'.$res['dj_id'].'.html">'.$res['dj_nom'].'</a>', $contenu);
		}

		$requete = mysql_query('SELECT * FROM donjons WHERE dj_actif = 1 AND dj_type="donjon"');
		while ($res = mysql_fetch_array($requete))
		{
			$contenu= preg_replace("#(\b|>)". regexAccents(preg_quote($res['dj_boss'], "#"))."(?![^<]*>)\b#i", '$1<a href="/'.$res['dj_type'].'s/'.caract_spec($res['dj_nom']).'-'.$res['dj_id'].'.html">'.$res['dj_boss'].'</a>', $contenu);
		}
		
		$requete = mysql_query('SELECT * FROM armes');
		while ($res = mysql_fetch_array($requete))
		{
			$contenu= preg_replace("#(\b|>)". regexAccents(preg_quote($res['a_nom'], "#"))."(?![^<]*>)\b#i", '$1<a href="/'.caract_spec($res['a_nom']).'-a'.$res['a_id'].'">'.$res['a_nom'].'</a>', $contenu);
		}
		
		$requete = mysql_query('SELECT * FROM remplacements')or die(mysql_error());
		while ($res = mysql_fetch_array($requete))
		{
			$contenu= preg_replace("#(\b|>)". regexAccents(preg_quote($res['rep_search'], "#"))."(?![^<]*>)\b#i", "$1" . $res['rep_replace'], $contenu);	
		}
		
		$contenu = preg_replace("@(^|\s)(https?://)?((www\.)?[a-z0-9\-]{2,30}\.[a-z]{2,4}(/.*)*)(\s|$)@i", "<a href=\"http://$3\">$0</a>",$contenu);
		
		
		return $contenu;
	}

?>

Bien sûr, ce script étant extrêmement lourd, il tourne grâce à une tâche planifiée.

A priori, il fonctionne très bien, mais il y a un gros problème : quand le script crée un lien sur du texte étant déjà à l'intérieur d'un lien, ça fait un magnifique lien dans un lien ce que je ne veux pas du tout.

Il y a donc deux possibilités :
- Modifier la regex pour qu'elle ne match pas le contenu appartenant déjà à un lien
- Ajouter un bout de script qui supprimerai, une fois l'exécution du script terminé, tous les liens emboités (sachant que le lien à conserver est toujours le premier à avoir été créé).

Dans les deux cas, c'est compliqué et j'ai un peu de peine à voir comment le faire... Bien sûr, la meilleure possibilité serait la deuxième, mais il s'agirait d'une regex très complexe (inutile de me donner de la doc, je la connais !).

Voilà, donc merci d'avance si quelqu'un aurait une solution
 
WRInaute accro
ça me rappel un truc ton histoire.

Il faut en fait que tu procède en deux étapes :

1/ pour chaque mot trouvé qui doit être transformé en lien tu change le mot dans le texte source en un tag unique et sans ambiguïté du genre %%1
2/ tu stocke dans un tableau indicé le code html du lien qui doit remplacer le mot.

ensuite tu boucle pour tous les mots a remplacer.

A la fin de cette première passe tu aura un texte avec des %%xxx dedans sachant que %%xxx ne fait pas parti des mots que tu cherche a remplacer.
Il te suffira ensuite, juste de boucler sur le tableau contenant le code html des liens pour remplacer les tags correspondant de ton texte modifié par le code html du tableau.

comme pour la fonction "regexAccents" qui commence par changer la chaîne avec un code intermédiaire avant d'y introduire le code définitif.

facile non ?
 
WRInaute discret
Ah oui merci, c'est effectivement une bonne idée ! :D

Enfin, maintenant c'est clair que j'aurais préféré directement avoir une regex mais ça c'est plutôt dur à mettre en place...

Bon, je vais coder tout ça ;)
 
WRInaute accro
Si ça peut t'aider voici comment ça se passe chez moi (CMS perso).

j'ai en base de données deux tables (entre autre) :
1/ l'une contiens entre autre le contenu textuel que je dois manipuler elle s'appel "editeur"
le champ 'text' entre autre contiens le texte de ma page.

2/ l'autre contiens une liste de mot que je souhaite transformer en liens sa structure est la suivante :
id (clé primaire auto incrément)
mot (le mot ou l'expression que je souhaite lier)
page (url de la page ciblé par le mot ça peut être vers un glossaire interne ou un partenaire qui veux être lié la dessus)
title (le texte de la balise title du lien)

un code qui fonctionne transposé du tiens ça donne :

Code:
<?php
	//Transforme une chaine en regex insensible aux accents. Exemple : Eléphant donne un truc comme (è|e|é|ê|ë|È|É|Ê|Ë)l(è|e|é|ê|ë|È|É|Ê|Ë)ph(a|à|á|â|ã|ä|å|À|Â|Ä|Á)nt
	function regexAccents($chaine) {
	   $accent = array('a','à','á','â','ã','ä','å','À','Â','Ä','Á','c','ç','Ç','e','è','é','ê','ë','È','É','Ê','Ë','i','ì','í','î','ï','Ï','Î','Ì','Í','o','ð','ò','ó','ô','õ','ö','Ô','Ö','Ò','Ó','u','ù','ú','û','ü','Ù','۟','Ü','Ú','y','ý','ý','ÿ','Ý');
	   $inter = array('%01','%02','%03','%04','%05','%06','%07','%08','%09','%10','%11','%12','%13','%14','%15','%16','%17','%18','%19','%20','%21','%22','%23','%24','%25','%26','%27','%28','%29','%30','%31','%32','%33','%34','%35','%36','%37','%38','%39','%40','%41','%42','%43','%44','%45','%46','%47','%48','%49','%50','%51','%52','%53','%54','%55','%56','%57');
	   $regex = array('(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)','(a|à|á|â|ã|ä|å|À|Â|Ä|Á)',
	'(c|ç|Ç)','(c|ç|Ç)','(c|ç|Ç)',
	'(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)','(è|e|é|ê|ë|È|É|Ê|Ë)',
	'(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)','(i|ì|í|î|ï|Ï|Î|Ì|Í)',   '(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)','(o|ð|ò|ó|ô|õ|ö|Ô|Ö|Ò|Ó)',         '(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)','(u|ù|ú|û|ü|Ù|۟|Ü|Ú)',
	'(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)','(y|ý|ý|ÿ|Ý)');
	   $chaine = str_ireplace($accent, $inter, $chaine);//Etape intermédiaire obligatoire, sinon il va y avoir une imbrication des remplacements quasi-infinie, chaque remplacement créant de nouveaux remplacements à faire.
	   $chaine = str_replace($inter, $regex, $chaine);      
	   return $chaine;
	}
	
	function auto_replace($idpage){
		require_once($_SERVER['DOCUMENT_ROOT'].'/util/config/config.php');
		require_once($_SERVER['DOCUMENT_ROOT'].'/util/function.php');
		
		// trouver le texte a modifier
		$sql = "SELECT text FROM ${prefix}editeur WHERE id = $idpage";
		$requete = s_mysql_query($sql);
		$res = mysql_fetch_array($requete);
		$contenu = $res[0];
		
		// 1ére itération sur les mots a transformer
		$requete = s_mysql_query("SELECT id,mot FROM `${prefix}link`");
		while ($res = mysql_fetch_array($requete)){
			$id = $res[0];
			$mot = $res[1];
			$contenu = preg_replace("/".regexAccents($mot)."/i", "%%$id", $contenu); 
		}

		// seconde itération sur les tags de transformation
		$requete = s_mysql_query("SELECT id,mot,page,title FROM `${prefix}link`");
		while ($res = mysql_fetch_array($requete)){
			$id = $res[0];
			$mot = $res[1];
			$page = $res[2];
			$title = $res[3];
			$contenu = preg_replace("/%%".$id."/", '<a href="'.$page.'" title="'.$title.'">'.$mot.'</a>', $contenu); 
		}
		return $contenu;
	}
?>

Comme tu le verra, comme j'ai une table qui contiens mes mots a transformer je n'ai pas besoin de m'ennuyer avec le tableau don je parlais ci dessus puisque c'est l'id du mot qui va me servir d'indice.
 
WRInaute discret
Oui, merci mais dans mon cas ce ne sera pas possible puisque, entre autres, j'ai plusieurs tables différentes (et j'en ajoute parfois). De plus, certains remplacements ne créent pas de liens mais juste des remplacements :D

Sinon, je me demandais, est-ce que tu penses que créer trop de liens internes pourrait nuire à mon référencement ? Quand je dis trop, c'est quand y'en a vraiment beaucoup sur chaque page, et qui sont parfois très redondants ! Je ne te parle pas du point de vue utilisateur mais surtout moteurs de recherche.
 
WRInaute accro
je me suis aussi posé cette question. En avoir c'est bien mais jusqu’où ? Wiki est une bonne base de réflexion je pense car ils en ont et cela ne semble pas nuire au contraire. faudrait faire un décompte sur des pages a eux bien rankées pour se faire une idée.

Dans mon cas c'est du liage "régional" donc ça n'a pas un fort impact sur le contenu, si ça rajoute 5/6 liens c'est un max donc j'ai pas poussé plus loin.
 
WRInaute accro
Deux choses:
- pour gérer les accents, il vaut mieux utiliser Normalizer::normalize($s, Normalizer::FORM_D) et enlever les accents avec un preg_replace( '/\pM/', '', $s ) par exemple.
- pour manipuler du HTML, il vaut mieux utiliser un vrai parser HTML. C'est très difficile d'obtenir une regex qui va gérer correctement tous les cas de figure, y compris le HTML mal formé...

Jacques.
 

➡️ Offre MyRankingMetrics ⬅️

pré-audit SEO gratuit avec RM Tech (+ avis d'expert)
coaching offert aux clients (avec Olivier Duffez ou Fabien Faceries)

Voir les détails ici

coaching SEO
Discussions similaires
Haut