SPIP - Contrib

[ar] [en] [es] [fr] [it]



Accueil du site > Navigation > Navigation transversale > Articles connexes par pertinence

Afficher les articles connexes, triés par pertinence.

vendredi 26 janvier 2007, par Beurt. Dernier ajout samedi 27 janvier 2007


Quelques noisettes et une goutte de php pour afficher les articles qui partagent le plus de mot-clés avec un autre article.


Les articles connexes

Il est très intéressant de pouvoir présenter à nos visiteurs les articles qui traient du même sujet que celui qu’ils sont en train de lire. Cela peut se faire simplement en listant les articles présents dans la même rubrique. On peut aussi le faire plus finement, en présentant aux visiteurs la liste des articles qui partagent les mêmes mots-clés que l’article qu’ils sont en train de consulter. Ce sont les articles connexes (pas forcément dans la même rubrique, mais reliés par leurs mots-clés à l’article courant).

Avec Spip, il est simple de faire le liste des articles connexes. Pour chaque mot-clé rattaché à l’article consulté, on affiche la liste des articles qui ont ce mot-clé. Cela donne la noisette suivante à placer dans vos squelettes d’articles :

Cette noisette qui contient une boucle dans une autre qui affiche le titre et un lien de chaque article qui a un mot-clé commun avec l’article de contexte [1]. Ainsi on a la liste des articles connexes. On peut affiner en informant le visiteur des mot-clés communs grâce à cette autre noisette à placer dans la boucle _Articles_Connexes :

Dans cette noisette, #_Contexte_Article:ID_ARTICLE signifie #ID_ARTICLE de la boucle _Contexte_Article, à ne pas confondre avec l’#ID_ARTICLE de la boucle dans laquelle on place la noisette (_Articles_Connexes). Pour en savoir plus sur la syntaxe des balises du type : #_Nom_Boucle:#NOMBALISE allez consulter la documentation de Spip sur les Balises non ambiguës.

Même chose pour #_Mots_Communs:TOTAL_BOUCLE.

Donc, vous devez adapter cette petite noisette à votre cas, si vous êtes dans une boucle globale qui se nomme _Contexte_Article, pas de problème ; sinon, n’oubliez pas de changer son nom.

Tout ça c’est très bien... Mais à condition d’avoir peu d’articles, et de mots-clés. Car, si comme moi, vous avez beaucoup d’articles et qu’ils ont chacun beaucoup de mots-clés ; la liste des articles connexes devient rapidement interminable (songez qu’elle contient tous les articles qui ont au moins un mot-clé commun avec l’article visité !). Pour éviter d’avoir 200 articles listés à chaque fois on peut se contenter de mettre dans la boucle _Articles_Connexes un critère {0,20} qui liste les 20 premiers articles par mots-clés. Bien sûr si vous avez beaucoup de mots-clés, il faudra lister moins de 20 articles par mots-clés, et peut-être pas tous les mots-clés non plus... Beaucoup de contraintes finalement et une solution peu satisfaisante qui est de prendre les x premiers articles des n premiers mots-clés, sans tenir compte de la pertinence de ce choix (dans les x premiers articles, il peut y en avoir qui n’ont qu’un seul mot-clé commun avec celui visité, alors qu’on voudrai plutôt afficher ceux qui en ont le plus).

Comment trier les —trop nombreux— articles connexes par pertinence et n’afficher que les plus intéressants pour le visiteur ?

Principe de la contrib’

Les articles connexes les plus pertinents sont ceux qui ont le plus de mots-clés communs avec l’article consulté. C’est ceux-là que l’on veut voir s’afficher en premier.

La contrib’ adapte donc la noisette présentée plus haut, qui est classique, pour pouvoir compter le nombre de mots-clés communs associés à chaque article connexe.

Spip, ne possède pas —encore— de mécanisme permettant ce comptage (bien qu’à venir dans Spip il y aura des filtres permettant d’affecter des valeurs à un tableau, voir : la liste des filtres sur spip.doc), il faut donc utiliser du PHP.

Noisette et noix de coco

Il faut toujours être dans un contexte d’article (donc que id_article soit défini).

On met en place le compteur pour chaque article qui a des mots-clés communs. Avec ce compteur on compte le nombre de mots-clés en commun. C’est dans un tableau en PHP. Voilà la noisette :

Le tableau $pertinence[ ] contient donc la liste des articles ayant des mots-clés communs avec notre article de contexte. Il contient aussi, pour chaque article de la liste, une valeur de pertinence qui correspond au nombre de mot-clés communs avec l’article de contexte.

On veut afficher les articles qui ont plus de 4 mots-clés communs (variable $maxcommun à changer selon vos goûts) avec notre article de contexte. On ne veut pas afficher plus de 20 articles (variable $maxarticles à changer selon vos goûts) au total.

Cette petite noisette grosse noix de coco est entrelacée dans du php : le tableau est trié de manière à ce que les articles les plus pertinents soient traités en premier. Puis, pour chaque élément du tableau, on va faire une boucle qui affiche un lien vers l’article, le nombre de mots-clés communs et la liste de ces mots-clés.

Et cela seulement si la pertinence est suffisante (condition sur $maxcommun) et qu’il y a moins de 20 articles connexes affichés (condition sur $maxarticles)

Cette noix de coco est complexe parce qu’elle est imbriquée dans du PHP...

À propos de l’intégration du PHP

J’ai découvert pas mal de choses sur l’intégration du PHP dans Spip. Ce qu’il faut principalement retenir ce sont les étapes du travail de Spip, telles qu’elles sont expliquées par ARNO* [2] ici : « Le PHP est interprété après les boucles ».

Donc, quand on intègre du PHP dans Spip, on doit systématiquement le séparer du reste par des balises <?php et ?> qui indiquent où commence et où fini le PHP.

Si vous souhaitez, comme dans cette contrib’, utiliser des valeurs calculées par Spip, ou issues de la base de donnée dans votre script PHP, récupérez-les en suivant cette méthode : Comment récupérer une « variable spip » en une variable PHP ?

Autre découverte : on peut couper le script PHP par ces balises partout, même au milieu d’un test de condition, si on oublie pas de le finir un peu plus loin (toujours encadré par les balises <?php et ?>). C’est ce que je fais dans le seconde noisettex, en commençant un test sur le tableau (« while (list($ks,$vs) = each($pertinence)) { » dont la fin se situe plus loin dans un autre « bloc » de PHP).

Dernière découverte et grosse difficulté (exposée par ARNO*) : on ne peut pas récupérer de variable PHP dans Spip car les BOUCLE/#BALISE sont transformées en PHP avant que les contenu du fichier ne soit lu par le serveur web ! Heureusement les contributeurs ont trouvé deux solutions.
- l’une simple que j’ai adopté, qui est expliquée ici : utiliser une variable PHP pour sélectionner une rubrique (par exemple). Ce n’est pas très élégant car cela m’oblige à faire une boucle dans laquelle l’ensemble des articles est sélectionné, ce qui coûte un peu au serveur web/MySQL.

- L’autre est élégante et puissante, elle utilise l’environnement de la page : en allemand : Tricks mit HTTP-Vars (moi je ne parle pas l’allemand ! Mais, la voici en plus ou moins français : variable php dans un critère de boucle ?). Elle est trop complexe pour moi.

Voilà, j’espère que cela vous sera utile. Je trouve en tout cas très agréable de pouvoir proposer à mes visiteurs une liste restreinte d’articles connexes qui sont toujours pertinents car ils partagent un nombre de mots-clés important.

Et vive la navigation transversale !

P.-S.

Le logo de cet article est un extrait d’une image de notafish que vous pouvez retrouver là : Chaîne du pont-levis elle est sous license cc : by-sa.

Notes

[1] Le contexte est une notion fondamentale de Spip : c’est un endroit où id_article est défini (c’est-à-dire soit dans une boucle « articles », soit en recevant id_article par inclusion).

[2] l’un des papas de Spip. Voir aussi L’histoire minuscule et anecdotique de SPIP.


Répondre à cet article

  • Merci beaucoup pour cette contrib que j’attendais depuis des années ! :)

    Par contre, j’ai eu beaucoup de difficulté à implémenter ce code pour les raisons suivantes :

    1) Il ne m’a pas été évident du premier coup quelles noisette je devais utiliser ni la façon dont elles devaient d’enchaîner.

    2) Plusieurs retours à la ligne ont été ommis à la fin de certains commentaires. Par exemple, la dernière ligne de code PHP :

    # on passe donc au suivant } }; devrait se lire :

    # on passe donc au suivant
    } };

    3) Pour une raison qui m’échappe (problème d’encodage d’un caractère?) le commentaire "#Puis pour chaque id_article" provoquait une erreur "Parse error". Retirer cette ligne a fait disparaître l’erreur !!

    4) Le commentaire "[(#Pour chaque article qui a ce mot clé]" devrait se lire "[(#REM)Pour chaque article qui a ce mot clé]

    5) Je suggère d’ajouter un commentaire dans le code pour indiquer le nom de la boucle contexte à remplacer. Par exemple : [(#REM) Remplacer "_Contexte_Article" par le non de la boucle contexte de l'article].

    Je suggère donc de corriger et tester le code et ensuide de fournir un fichier HTML à télécharger pour éviter toute confusion et d’assurer l’intégrité du code.

    Voici mon code final, au cas où ça pourra en aider certains :

    Répondre à ce message

    • Il y a aussi cette corretcion à appliquer :

      if ($vs > maxcommun-1) {
      $i++;
      echo $i;
      if ($i==maxarticles) break;

      doit être

      if ($vs > $maxcommun-1) {
      $i++;
      echo $i;
      if ($i==$maxarticles) break;

      (Il manque le signe $ aux variables.)

      Répondre à ce message

      • Bonjour,

        J’ai un p’tit blème quand mon article n’a pas de mots clés 2 lignes d’erreurs s’affichent :

        Warning: arsort() expects parameter 1 to be array, null given in /home.8/p/a/t/patcatna/www/ecrire/public.php(173) : eval()'d code on line 253
        Warning: Variable passed to each() is not an array or object in /home.8/p/a/t/patcatna/www/ecrire/public.php(173) : eval()'d code on line 257

        Cela semble venir de :

        if ($vs > maxcommun-1) {
        $i++;
        if ($i==maxarticles) break;

        En faisant les corrections du post ci-dessus c pire (déclaration des variables...)

        Merci de votre aide

        Patrice

        Répondre à ce message

    Retour au début des forums

  • Afficher les articles connexes, triés par pertinence.

    11 août 2007 16:44, par Philippe

    J’ai comme l’impression que cela ne fonctionne plus sous une 1.9.2b

    Répondre à ce message

    Retour au début des forums



Suivre la vie du site RSS 2.0 | Plan du site | Espace privé | Charte et fonctionnement SPIP-Contrib | SPIP | L'autre.net