[spip-dev] lisibilité, visibilité, référencement

Bonjour à tous,

La discussion sur le référencement semble se calmer.
C'est le moment de reprendre le pb sur le plan des techniques
du graphiste et de l'informaticien.

Je voudrais d'abord dire que soigner le référencement n'est pas nécessairement un souci commercial.
Quand on va dans une bibliothèque publique,
on s'attend non seulement à y trouver des ouvrages intéressants,
mais aussi un catalogue permettant de les trouver facilement;
autrement, on trouve que la qualité du service préjuge mal du fonds,
on va voir ailleurs et c'est du gâchis.

De même, si on se donne la peine de faire un site Web, c'est pour être lu.
Pour reprendre une dichotomie classique des graphistes, il faut donc soigner
la lisibilité
(le texte se lit avec plaisir, typiquement parce que la police est bien choisie)
et la visibilité
(le texte donne envie d'être lu, typiquement parce que la mise en pages est attirante au premier regard).

Un internaute dimensionnant arbitrairement ses fenêtres,
l'auteur d'un document HTML n'en maîtrise pas totalement la mise en pages.
Par rapport à un document imprimé, la visibilité d'un document HTML
a donc un outil de moins, et l'intérêt du référencement est de le compenser.

Proposer de nouveaux champs spéficiques aux balises ne me semble néanmoins pas opportun.
Préciser aux rédacteurs que l'actuel champ Description alimentera la balise du meme nom
est de nature à clarifier sa fonction par rapport au chapeau,
et donc à soulager l'administrateur du site dans le contrôle de l'usage de ces champs.

Maintenant le problème technique: le champ Description étant aussi destiné à une lecture humaine,
il va contenir beaucoup de superflu (article, date, ponctuation), des répétitions,
et peut dépasser la limite de 1024 caractères imposée par certains moteurs de recherches,
surtout lorsqu'on itère le procédé sur plusieurs champs.

La solution que j'ai trouvée est d'écrire un filtre qui mémorise dans une variable rémanente
les mots déjà inclus dans le résultat final, et évite d'y mettre les chaînes considérées comme
non significatives:

function stripnonletterandrep ($l, $init='')
{
   static $dejavu ;
   $r = "";
   if ($init)
     $dejavu = $init;
   else
     {
  // cf entite_html
       $l = ereg_replace('&([^;]*;)','&\1',$l);
       $l = ereg_replace('&([^;]*;)',' ',$l);
       foreach (split("[0-9\(\){}',.:\?!/ ]+",$l) as $x)
   {
    if (strlen($x) > 3)
      {
        $x = htmlspecialchars(strtolower($x));
        if (!strpos($dejavu,$x))
     {
      $dejavu .= " $x";
      if (strlen($dejavu) > 1024) return $r;
      $r .= " $x";
     }
     }
    }
     }
   return $r;
}

Comme cette fonction peut être utilisée plusieurs fois dans un processus,
il est nécessaire d'initialiser sa variable rémanente avant utilisation,
ce qui conduit à écrire cette petite horreur
(aux deux premières occurrences de 'content'):

<meta name="Description"
       content="[(#NOM_SITE_SPIP|stripnonletterandrep{' '})]<BOUCLE_head_D(RUBRIQUES){unique){", "}
  >[(#DESCRIPTIF|stripnonletterandrep) ][(#TITRE|stripnonletterandrep) ]</BOUCLE_head_D>">
<meta name="Keywords"
       content="[(#NOM_SITE_SPIP|stripnonletterandrep{' '})]<BOUCLE_head_K(ARTICLES){unique}{", "}
  ><BOUCLE_keywords(MOTS){id_article}{unique}{", "}
  >[(#TITRE|stripnonletterandrep)]</BOUCLE_keywords></BOUCLE_head_K>">
<meta name="Author"
       content="<BOUCLE_head_A(ARTICLES){", "}
  ><BOUCLE_author(AUTEURS){id_article}{unique}{", "}
  >[(#NOM|htmlspecialchars)]</BOUCLE_author></BOUCLE_head_A>">

Autrement dit, je référence NOM_SITE_SPIP juste pour provoquer l'appel d'un filtre,
qui va ignorer cet argument, pour ne considérer que le 2e (l'initialiseur).
C'est pas démesurément intuitif. Y a-t-il moyen de faire mieux ?

Merci d'avoir lu jusqu'ici !

      Emmanuel

là .. j'ai pas tout compris.
  en gros, si on appelle la fonction avec un init, on force
à l'affecter, sinon, on ressort de l'argument que les mots
qu'on n'a pas déjà vu, c'est ça ?
  dans ce cas, ça serait pas plus simple de mettre ça dans une variable
globale (initialisée pour chaque page) plutot que static (rémanente
entre 2 pages si j'ai bien compris) ?

  Ensuite, le strpos, ça serait pas plus simple de passer par une
hashtable plutot ?
  foreach(... as $x) {
      if(!$dejavu[$x]) {
          $dejavu[$x]=1;
          $r.=" $x";
      }
  }

À+, Pif.

function stripnonletterandrep ($l, $init='')

  là .. j'ai pas tout compris.
  en gros, si on appelle la fonction avec un init, on force
à l'affecter, sinon, on ressort de l'argument que les mots
qu'on n'a pas déjà vu, c'est ça ?

oui

  dans ce cas, ça serait pas plus simple de mettre ça dans une variable
globale (initialisée pour chaque page) plutot que static (rémanente
entre 2 pages si j'ai bien compris) ?

non, pas entre 2 pages: justement le squelette que je donne ensuite utilise
cette fonction pour construire 2 listes différentes, d'où le besoin d'initialiser
quand on veut, que la variable soit globale ou rémanente. Quant au choix global/rémanent,
je trouve plus clair de choisir rémanent quand on peut: ça indique que cette variable
n'est utilisée que par cette fonction.

  Ensuite, le strpos, ça serait pas plus simple de passer par une
hashtable plutot ?

Les algorithmes de recherche de chaine et de hachage sont très variés
et puissants. Je ne sais pas a priori lesquels PHP utilisent, et comme
sa fonction microtime mesure la durée du service et pas la durée du processus,
les tests ne sont pas fiables. Mais ta remarque est tout à fait juste au moins en théorie.

      Emmanuel

function stripnonletterandrep ($l, $init='')

  là .. j'ai pas tout compris.
  en gros, si on appelle la fonction avec un init, on force
à l'affecter, sinon, on ressort de l'argument que les mots
qu'on n'a pas déjà vu, c'est ça ?

oui

  dans ce cas, ça serait pas plus simple de mettre ça dans une variable
globale (initialisée pour chaque page) plutot que static (rémanente
entre 2 pages si j'ai bien compris) ?

non, pas entre 2 pages: justement le squelette que je donne ensuite utilise
cette fonction pour construire 2 listes différentes, d'où le besoin d'initialiser
quand on veut, que la variable soit globale ou rémanente. Quant au choix global/rémanent,
je trouve plus clair de choisir rémanent quand on peut: ça indique que cette variable
n'est utilisée que par cette fonction.

  Ensuite, le strpos, ça serait pas plus simple de passer par une
hashtable plutot ?

Les algorithmes de recherche de chaine et de hachage sont très variés
et puissants. Je ne sais pas a priori lesquels PHP utilisent, et comme
sa fonction microtime mesure la durée du service et pas la durée du processus,
les tests ne sont pas fiables. Mais ta remarque est tout à fait juste au moins en théorie.

      Emmanuel

> dans ce cas, ça serait pas plus simple de mettre ça dans une variable
> globale (initialisée pour chaque page) plutot que static (rémanente
> entre 2 pages si j'ai bien compris) ?

non, pas entre 2 pages: justement le squelette que je donne ensuite
utilise
cette fonction pour construire 2 listes différentes, d'où le besoin
d'initialiser
quand on veut,

Ok, j'avais pas tout décodé dans le squelette :wink:

que la variable soit globale ou rémanente. Quant au
choix global/rémanent,
je trouve plus clair de choisir rémanent quand on peut: ça indique que
cette variable
n'est utilisée que par cette fonction.

  Je ne savais pas trop à quoi correspondait "static" en php.
  Mais dans ce cas, on est d'accord, static est plus propre.

> Ensuite, le strpos, ça serait pas plus simple de passer par une
> hashtable plutot ?

Les algorithmes de recherche de chaine et de hachage sont très variés
et puissants.

  strpos est forcement linéaire donc, a priori, moins efficace pour
trouver simplement l'existence d'une sous chaine.
  mais bon, c'est du détail tout ça, je r'tourne bosser :wink:

À+, Pif.