[RESOLU] Extraire x caractères à une position précise et les surligner sur une recherche

Avatar du membre
Eléphanteau du PHP | 25 Messages

30 sept. 2015, 18:50

Bonjour,

J'ai un gros texte ou j'aimerais en extraire qu'une partie selon le terme recherché. Ci dessous, une partie du code que j'utilise..

les variables connues :

$keywords : le terme recherché...
$texte : un texte de ~16'000 caractères
$description : résumé du texte sur un peu près 350 caractères (synopsis)

Si la variable $keywords comporte qu'un seul terme, mon exemple ci-dessous fonctionne, il va afficher ma keywords et 320 caractères à gauche de celui ci et également à droite

Par contre si j'ai deux termes dans ma variable $keywords il m'affiche uniquement la desciption et c'est pas ce que je souhaite... si les deux termes recherchés sont trop éloignés dans le texte (ce qui arrivera forcément..) qu'il en prenne au moins un des deux termes pour afficher 320 caractères à gauche de celui ci et également à droite..
<?php

 // Nettoyage...
 
	$keywords = htmlentities(htmlspecialchars($_GET['s'], ENT_COMPAT)); 
	$keywords = trim(strip_tags($keywords));
	$keywords = html_entity_decode($keywords);

	$keywordUnclean = trim(preg_replace("/&#?[a-z0-9]+;/i",'',(strip_tags($keywords))));
	$keywordClean = substr(preg_replace('/\s+/', ' ', $keywordUnclean), 0, 255);

// +---------- Transfo pour surlignage ---------------+
	
	$keywords3 = explode(' ', $keywordClean);	
	
// +---------- Le premier mot clef de plus de 4 lettres est gardé pour le positionner dans le texte ---------------+	  

	$wordsy    = array_filter(explode('+', $keywords), function($p) { return strlen($p) > 4; });
	$keyword2  = reset($wordsy);

// +---Connexion à ma bd et tout le tralala ----- +

//..................................
	
// +------  Cherche les keywords qui sont présent dans le texte ----------- +	
		
		$pos = stripos($texte, $keyword2); // insensible à la casse, sinon strpos
		if ($pos === false) {
		$decription = "$description";
		} else {
		$description = "$texte";
        }
		
		$texte = str_replace(array("\r\n", "\n", "\n\r"), ' ', $texte);

		$i = stripos($texte, $keyword2);
		if ($i <= 320)
			{
				$r = substr($texte, 0, $i);
			}
		else
			{
    // par la gauche
		$lim = -320;
		while (substr($texte, $i + $lim--, 1) !== ' ') // coupure sur le premier espace trouvé
			{
        continue;
			}
		$r  = substr($texte, $i + $lim + 2, abs($lim) - 2);
			}
 
		$start = $i + strlen($keyword2);
		if (($start + 320) >= strlen($texte))
			{
		$r .= substr($texte, $i);
		}
		else
		{
    // par la droite
		$lim = 320;
		while (substr($texte, $start + $lim++, 1) !== ' ')
			{
        continue;
			}
		$r .= substr($texte, $i, --$lim + strlen($keyword2));
		}

		$description ="$r";
		
		
// +-------------- je prépare pour la mise en gras -----------+

		$motif='`\b(('.implode('|',$keywords3).')s?)\b`si';
		$sortie='<span class="highlight_word">$1</span>';
		$sortie2='<span class="highlight_word2">$1</span>'; // question de couleur par rapport à $sortie
		$texte = preg_replace($motif,$sortie,$texte);
		$nomsite = preg_replace($motif,$sortie2,$nomsite);
		$description = preg_replace($motif,$sortie,$description);
	?>
J'espère avoir été clair dans mon explication (pas évident j'en conviens..)

D'avance merci de m'éclairer sur mon problème
Yule

Mammouth du PHP | 737 Messages

01 oct. 2015, 10:34

Salut,

Tu as un exemple concret car en effet c'est pas évident à comprendre ^^

Mega
;)
Dyslexics are teople poo

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 8516 Messages

01 oct. 2015, 12:04

Bonjour,

Ce que tu cherches à faire est ce qu'on appelle un "snippet".

Avec ce mot-clé, tu devrais trouver plusieurs pistes via Google pour t'aider à le faire car c'est quelque chose d'assez classique.

Voici un exemple de fonction PHP :
https://snippetsofcode.wordpress.com/20 ... ts-in-php/

D'autres fonctions plus évoluées :
https://stackoverflow.com/questions/129 ... -and-mysql

Ou même directement en SQL :
http://stackoverflow.com/a/24739333
Quand tout le reste a échoué, lisez le mode d'emploi...

Avatar du membre
Eléphanteau du PHP | 25 Messages

01 oct. 2015, 15:57

Hello,

Extra merci, je vais zieuter tout ceci et adapter mon code en conséquence

Bonne bonne

Yule

Avatar du membre
Eléphanteau du PHP | 25 Messages

01 oct. 2015, 17:11

Re,

J'ai donc opté pour le snippet ci-dessous (utile si + de 1 keyword)...... Tout fonctionne sauf que je n'arrive pas à limiter le texte en sortie à 320 caractères avec l'ensemble des keywords

si j'ai 3 keywords, il faut dans les 320 caratères que j'aie une extraction minimum des 3 keywords pas juste les 320 premiers caractères....

Comme ce résultat va s'afficher dans un moteur de recherche , je ne tiens pas a avoir des réponses avec 700 ou 1000 caractères.

J'ai donc fait simplement (d'ou certainement mon erreur) strlen sur ma variable $description, et il m'affiche moins de 100 caractères, pourtant sur le texte de sortie, j'ai au moins 500 caractères)
<?php
function excerpt($texte, $keyword)
{
//words
$words = join('|', explode(' ', preg_quote($keyword)));

//lookahead/behind assertions ensures cut between words
$s = '\s\x00-/:[email protected]\[-`{-~'; //character set for start/end of words
preg_match_all('#(?<=['.$s.']).{1,30}(('.$words.').{1,30})+(?=['.$s.'])#uis', $texte, $matches, PREG_SET_ORDER);

//delimiter between occurences
$results = array();
foreach($matches as $line) {
    $results[] = htmlspecialchars($line[0], 0, 'UTF-8');
}
$result = join(' <b>(...)</b> ', $results);

//highlight
$result = preg_replace('#'.$words.'#iu', "<span class=\"highlight_word\">\$0</span>", $result);

return $result;
}

echo excerpt($texte, $keyword);

// partie que j'ai rajouté sans succès..ou plutôt très mitigé...
/*
$description = excerpt($texte, $keyword);

$lg_max = 320; 
	if (strlen($description) > $lg_max) 
	{ 
    $description = substr($description, 0, $lg_max); 
    $last_space = strrpos($description, " ");  
    $description = substr($description, 0, $last_space)."..."; 	
	} 
	
echo"$description";
*/
?>
Une idée ?
A toute
Yule

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 8516 Messages

01 oct. 2015, 17:38

Voila comment je le ferrai, en modifiant légèrement la fonction que tu as retenue :
echo snippet_max ($texte, $keyword, 320);



function snippet_max($texte, $keyword, $strlen_max) {
	//words
	$words = join('|', explode(' ', preg_quote($keyword)));

	//lookahead/behind assertions ensures cut between words
	$s = '\s\x00-/:[email protected]\[-`{-~'; //character set for start/end of words
	preg_match_all('#(?<=['.$s.']).{1,50}(('.$words.').{1,50})+(?=['.$s.'])#uis', $texte, $matches, PREG_SET_ORDER);

	$result = "";
	foreach($matches as $line) {
		if (strlen($result.htmlspecialchars($line[0], 0, 'UTF-8')."... ") > $strlen_max) break;
		$result .= htmlspecialchars($line[0], 0, 'UTF-8')."... ";
	}

	//highlight
	$result = preg_replace('#'.$words.'#iu', "<span class=\"highlight_word\">\$0</span>", $result);

	return $result;
}
Quand tout le reste a échoué, lisez le mode d'emploi...

Avatar du membre
Eléphanteau du PHP | 25 Messages

01 oct. 2015, 19:00

Merci je viens d'essayer et c'est en partie ok, je vais encore adapter d'autre partie pour essayer d'arriver à mon but final.
J'ai trop de question hypothétique et ça ne peut fonctionner comme je le souhaiterais, avant de nettoyer mon script faut que je le fasse dans ma tête..

Encore mille merci !

Avatar du membre
Eléphanteau du PHP | 25 Messages

01 oct. 2015, 21:10

re,

J'ai donc intégré tout ceci dans mon code et je coince sur un dernier point qui fausse mon affichage...

Mon $keyword peut se composer de plusieurs termes, exemple : manger une pomme
$keywords ="manger une pomme";
comment indiquer sur cette ligne
$words = join('|', explode(' ', preg_quote($keywords)));
ne garde que les mots de plus de 4 lettres.... (ca va m'éviter les, la, une, des, vos, et, ma etc....)

J'ai essayé avec un foreach en vain..
$words = join('|', explode(' ', preg_quote($keywords)));
		
		foreach ($words as $key=>$value)
		{
				if (strlen($value) <= 4)
				unset($words[$key]);
			}

Merci
yule

Avatar du membre
Eléphanteau du PHP | 25 Messages

05 oct. 2015, 18:21

Hello,

j'ouvre à nouveau ce poste car je viens de remarquer un point gênant dans mes résultats

la fonction fonctionne très bien, il prend bien en compte les keywordsy de 3 caractère au minimum, par contre ça coince au niveau de la surbrillance, il prends en compte tous les caractères et j'aimerais aussi qu'il surbrille dès 4 caractères
$keywords ="a vendu une moto";
barcelone moto rent - location scooter sauter la navigation accueil tarifs 50cc 125cc (offre spéciale jusqu’au 31 décembre) 250cc prix + de 400cc... prix réservation contact services services/livraison bon plan questions / réponse partenaires share location de scooter a barcelone barcelona moto...
function snippet_max($texte, $keywordsy, $strlen_max) {
		
		//$keywordsy =  str_replace('  ',' ',preg_replace("# [[:alnum:]]{1,3}[\.,;:]? #",  "", str_replace(' ','  ',$keywordsy)));
		
		while(preg_match("# ([[:alnum:]]{1,3}) #", $keywordsy))
		$keywordsy =  preg_replace("#( [[:alnum:]]{1,3} )#", " ", $keywordsy);
	
		$words = join('|', explode(' ', preg_quote($keywordsy)));
		
		//lookahead/behind assertions ensures cut between words
		$s = '\s\x00-/:[email protected]\[-`{-~'; //character set for start/end of words
		preg_match_all('#(?<=['.$s.']).{1,100}(('.$words.').{1,100})+(?=['.$s.'])#uis', $texte, $matches, PREG_SET_ORDER);

		$result = "";
		foreach($matches as $line) {
		if (strlen($result.htmlspecialchars($line[0], 0, 'UTF-8')."... ") > $strlen_max) break;
		$result .= htmlspecialchars($line[0], 0, 'UTF-8')."... ";
		}
		//highlight
		$result = preg_replace('#'.$words.'#iu', "<span class=\"highlight_word\">\$0</span>", $result);
		return $result;
		}
$description = snippet_max($texte, $keywordsy, 400);
Merci pour votre aide
Yule