Jump to content

Créer son mini moteur de recherche pour son site


Zod

Recommended Posts

Bonjour, j'aurais une question pour mon site, le principe de mon site est de lire les flux rss de plusieurs sites de news d'info et de les afficher.

Jusque là c'était simple, seulement maintenant j'aimerais me créer un mini moteur de recherche afin de pouvoir retrouver tout ce qui est passé sur mon site.

Donc dans l'absolu je pensais faire quelque chose qui lirais les titres des news et sauvegarderais les mots contenus dans chaque titre, ainsi que le lien du titre dans un base SQL. Ainsi, quand je lance une recherche sur un mot donné dans ma base SQL, le résultat de la recherche serait les liens qui contiennent le mot recherché.

Seul problème, je n'ai aucune idée comment m'y prendre pour écrire quelque chose qui scanne les différents titres et les envoit dans une base SQL :eeek2:

Si vous pouviez m'aider ça serait super :)

Merci d'avance

Link to comment
Share on other sites

Un tit moteur de recherche : sphider

Sphider version ameliore du moteur de recherche en php : phpdig

Sphider peut gerer environ 400 000 pages correctement (selon les dire de l'auteur j'ai pas teste :byebye: )

Le php inplique qu'il est facile d'utilisation mais l'indexation est longue, longue :pleure:

merci je vais voir ça :)

@quarky désolé, j'ai pas pensé que ça pouvait être pris pour de la pub :)

Link to comment
Share on other sites

Perso, j'ai développer moi-même ma fonction de recherche. Je n'ai pas des milliers d'enregistrements, donc ça suffit largement je trouve. J'ordonne mes résultats par code article/désignation d'article/sous-titre d'article/description de l'article. Si ça peut aider, voici mon code (j'ai pas pris le temps d'enlever les trucs inutiles...) :

(contactez-moi par MP si vous voulez savoir le nom du site pour voir comment ça fonctionne en vrai)

<?
if (isset($_POST['search']) && trim($_POST['search'])!='' & $_POST['search']!='Votre recherche...') {
$_SESSION['search']=$_POST['search'];

// on passe les mots recherchés en minuscules
$recherche = strtolower($_POST['search']);

// on remplace les ' + , :  par des espaces
$mots = str_replace('+', ' ', trim($recherche));
$mots = str_replace('\'', ' ', $mots);
$mots = str_replace(',', ' ', $mots);
$mots = str_replace(':', ' ', $mots);
$mots = str_replace('  ', ' ', $mots);

// on place les differents mots dans un tableau
$tab = explode(' ' , $mots);

//===================================================================
//================ RECHERCHE POUR TOUS LES MOTS =====================
//===================================================================
// on compte le nbr d'élément du tableau.
$nb = count($tab);
//on prépare la requête SQL.
$sql = "select * from articles where actif='1' AND code like '%$tab[0]%' ";
// on boucle pour integrer tous les mots dans la requête
for($i = 1; $i < $nb; $i++) {
  $sql .= "OR code like '%$tab[0]%' ";
}
$sql .= "UNION select * from articles where actif='1' AND designation like '%$tab[0]%' ";
// on boucle pour integrer tous les mots dans la requête
for($i = 1; $i < $nb; $i++) {
  $sql .= "OR designation LIKE '%$tab[$i]%' ";
}
$sql .= "UNION select * from articles where actif='1' AND sous_titre like '%$tab[0]%' ";
// on boucle pour integrer tous les mots dans la requête
for($i = 1; $i < $nb; $i++) {
  $sql .= "OR sous_titre LIKE '%$tab[$i]%' ";
}
$sql .= "UNION select * from articles where actif='1' AND description like '%$tab[0]%' ";
// on boucle pour integrer tous les mots dans la requête
for($i = 1; $i < $nb; $i++) {
  $sql .= "OR description like '%$tab[$i]%' ";
}
$sql .= "LIMIT 0,100";
//echo "Requête : <br />".$sql."<br />";
$result = mysql_query($sql) or die("Problème de recherche...");
$nb_trouve = mysql_numrows($result); // on recupère le nombre d'enregistrements
if ($nb_trouve != 0) {
	if ($nb_trouve == 1)
		echo "<h6 style='margin:10px;'>".$nb_trouve." seul article corresponds à votre recherche :</h6>";
	else
		echo "<h6 style='margin:10px;'>".$nb_trouve." articles correspondent à votre recherche :</h6>";

	while ($val = mysql_fetch_array($result)) {
		// Préparation du titre de l'article
		$titre_article=stripslashes($val['designation']." (Réf. ".$val['code'].")");
		for($i = 0; $i < $nb; $i++) {
			$titre_article = surligner($tab[$i],$titre_article);
		}
		if ($val['sous_titre'] != "") {
			// Préparation du sous-titre de l'article
			$ss_titre_article=stripslashes($val['sous_titre']);
			for($i = 0; $i < $nb; $i++) {
				$ss_titre_article = surligner($tab[$i],$ss_titre_article);
			}
		}
		// Préparation du texte de l'article
		$texte_article = substr(notag(stripslashes($val['description'])),0,300);
		for($i = 0; $i < $nb; $i++) {
			$texte_article = surligner($tab[$i],$texte_article);
		}
		// Affichage du résultat
		echo "<table style='margin-top:10px;' rules='none' border='0' align='center' width='95%' cellspacing='0' cellpadding='3' >";
		echo "<tr><td colspan='2' nowrap>";
		echo "<div width='80%'><li><a class='souligne' href='article_fiche.php?article=".$val['code']."'>".$titre_article."</a>";
		if ($val['sous_titre'] != "") {
			echo "<div style='margin-left:16px;COLOR: #336085;'><i>".$ss_titre_article."</i></div>";
		}
		echo "</td></tr>";
		echo "<tr><td valign='top' width='5%'>";
		// Affichage photo si présente
		if ($val['photo']==1) {
			if (file_exists("photos/".$val['code']."_petit.gif")) {
				echo "<a class='souligne' href='article_fiche.php?article=".$val['code']."'><img width='50' align='absbottom' src='photos/".$val['code']."_petit.gif'></a>";
			}else {
				if (file_exists("photos/".$val['code']."_petit.jpg")) {
					echo "<a class='souligne' href='article_fiche.php?article=".$val['code']."'><img width='50' align='absbottom' src='photos/".$val['code']."_petit.jpg'></a>";
				}else {
					if (file_exists("photos/".$val['code']."_petit.png")) {
						echo "<a class='souligne' href='article_fiche.php?article=".$val['code']."'><img width='50' align='absbottom' src='photos/".$val['code']."_petit.png'></a>";
					}
				}
			}
		}			
		echo "</td>";
		echo "<td><div style='text-align: justify;'>".$texte_article."(...)</div><br /></div>"."</td>";
		echo "</tr>";
		echo "</table>";
	} // Fin du WHILE

} else {
	echo "<br /><br /><h6>Aucun résultat pour votre recherche...</h6>";	
}


} else {

echo "<br /><br /><h6>Vous n'avez précisé aucun mot dans votre recherche...</h6>";	
unset($_SESSION['search']);
}

?>

Link to comment
Share on other sites

Sympa de partager ;)

Quelques petites remarques personnelles. Je ne suis pas un dieu du php, je peux me planter évidemment. Ce ne sont que quelques suggestions/remarques qui ne vallent que ce qu'elles valent.

Pour le début j'aurais plutôt eu tendance à utiliser une regex plutôt que 5 str_replace. Je suis d'accord que str_replace est plus rapide, mais quitte à le lancer 5 fois, autant utiliser une seule regex.

	$mots = str_replace('+', ' ', trim($recherche));
$mots = str_replace('\'', ' ', $mots);
$mots = str_replace(',', ' ', $mots);
$mots = str_replace(':', ' ', $mots);
$mots = str_replace('  ', ' ', $mots);

$mots = preg_replace('/[+\,: ]+/', ' ', trim($recherche));

Et pourquoi ne pas tout simplement remplacer tous les caractères non alphanumériques directement par un espace ?

$mots = preg_replace('/\W+/', ' ', trim($recherche));

Je trouve ça plus propre.

if ($nb_trouve == 1) echo "<h6 style='margin:10px;'>".$nb_trouve." seul article corresponds à votre recherche :</h6>";

Pourquoi pas tout simplement :

if ($nb_trouve == 1) echo "<h6 style='margin:10px;'> un seul article correspond à votre recherche :</h6>";

? :byebye:

Une dernière remarque :

Les if à ralonge, ce n'est pas la joie à debugger. C'est pour ça que je trouve ça mieux de mettre la condition la plus courte en premier ou alors de remplacer le corps du if ou du else par une fonction.

(J'ai passè plusieures heures à juste comprendre dans un code de quelques centaines de lignes où se terminaient certaines instructions. Bon le code n'était pas indenté et le php et le html étaient allègrement mélangés. Ce qui n'est pas le cas ici, mais pourquoi se priver ?).

	if ($nb_trouve != 0) {
[snip...]
} else {
	echo "<br /><br /><h6>Aucun résultat pour votre recherche...</h6>";	
}

J'aurais bien vu un truc comme ça :

 if (!$nb_trouve)
{
echo "<br /><br /><h6>Aucun résultat pour votre recherche...</h6>";
return 1;
}
echo "<h6 style='margin:10px;'> " . ($nb_trouve==1 ? "un seul article correspond" : "$nb_trouve articles correspondent") . "à votre recherche :</h6>"
[...]

</IMHO>

Link to comment
Share on other sites

Merci pour les conseils :-)

Pour les expressions régulières, c'est juste ! C'est surtout que j'ai ajouter les caratères à remplacer au fur et à mesure. Et aussi que j'ai parfois un peu de mal avec les expressions régulières.

Pour le "un seul article correspond à votre recherche", c'est pas faux. Je vais changer ça de suite.

Pour les conditions d'exclusion, c'est pas bête aussi...Mais bon, vu que j'indente toujours bien mon code (et que j'utilise Notepad++ qui fait un semblant d'indentation graphique) ça ne me dérange pas trop encore. Mais à l'avenir, j'essayerai plutôt de procéder comme tu me l'as dit.

Merci encore pour tes conseils ;)

Link to comment
Share on other sites

Oh merci beaucoup :)

Je ne comprends pas tout vu que je suis une quiche en php (ça aide pas :yes:) mais je vais regarder tout ça à tête reposée.

Le plus dur sera pour moi de lancer la requete qui remplie la base SQL à chaque fois que le parseer récupère de nouvelles données depuis le rss, histoire ce générer un historique du site :)

Link to comment
Share on other sites

Sympa de partager :D

Quelques petites remarques personnelles. Je ne suis pas un dieu du php, je peux me planter évidemment. Ce ne sont que quelques suggestions/remarques qui ne vallent que ce qu'elles valent.

Pour le début j'aurais plutôt eu tendance à utiliser une regex plutôt que 5 str_replace. Je suis d'accord que str_replace est plus rapide, mais quitte à le lancer 5 fois, autant utiliser une seule regex.

	$mots = str_replace('+', ' ', trim($recherche));
$mots = str_replace('\'', ' ', $mots);
$mots = str_replace(',', ' ', $mots);
$mots = str_replace(':', ' ', $mots);
$mots = str_replace('  ', ' ', $mots);

$mots = preg_replace('/[+\,: ]+/', ' ', trim($recherche));

Et pourquoi ne pas tout simplement remplacer tous les caractères non alphanumériques directement par un espace ?

$mots = preg_replace('/\W+/', ' ', trim($recherche));

Je trouve ça plus propre.

ta remarque sur la fonction str_replace m'a mis le doute... mais finalement ma première impression était bonne!

str_replace accepte un tableau pour les paramètres search et replace (respectivement les 1° et 2° paramètres), comme le précise l'explication sur php.net

Il peut donc ne faire qu'un seul str_replace au lieu de 5, et éviter en même temps les regexp (inutilement couteux en ressources dans le cas qui nous occupe)

Link to comment
Share on other sites

Ah oui tu as raison. :fumer:

Effectivement, ça va plus vite.

 time php str.php

real	0m1.143s
user	0m0.788s
sys	 0m0.006s

time php regex.php

real	0m5.800s
user	0m2.826s
sys	 0m0.006s

5000 remplacement sur une chaîne de 3000 caractères.

Ceci dit la solution des regex est meilleure dans le cas où il y a plusieurs espaces.

$string = "un deux  trois	  quatre cinq";

donnera

un deux trois   quatre cinq

avec la technique du str_replace (deux espaces par un seul), alors qu'avec la regex qui matche un ou plus, ça remplace par exactement par un espace.

Et c'est aussi plus pratique dans le cas où on voudrait remplacer tout ce qui n'est pas un caractère alphanumérique. Par ailleurs je ne suis pas persuadé que faire une regex soit plus lent que de parcourir à chaque fois un tableau avec tout les caractères un par un.

Mais j'ai la flemme de remplir un tel tableau à la main pour tester :chinois:

Link to comment
Share on other sites

ta remarque sur la fonction str_replace m'a mis le doute... mais finalement ma première impression était bonne!

str_replace accepte un tableau pour les paramètres search et replace (respectivement les 1° et 2° paramètres), comme le précise l'explication sur php.net

Il peut donc ne faire qu'un seul str_replace au lieu de 5, et éviter en même temps les regexp (inutilement couteux en ressources dans le cas qui nous occupe)

Hello windu.2b,

Ah oui, pas bête le coup du tableau. En plus, je l'ai utilisé derniérement, mais vu que ma fonction de recherche est assez ancienne, je n'avais pas pensé à revenir dessus.

Je vais me faire ça demain.

Merci :transpi:

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...