N'importe quoi. Alors je vais expliquer pourquoi ton système de calcul (qui, lui, n'a jamais été expliqué) ne fonctionne pas.
// Calcul des gains en popularite
$query = "SELECT id_article, COUNT(*) AS referers, SUM(visites) AS visites ".
"FROM spip_referers_articles GROUP BY id_article";
$result = spip_query($query);
Le calcul se base uniquement sur la table spip_referers_articles. Déjà, si on n'active pas les referers (et ils sont désactivés par défaut), on n'a pas de "popularite" (alors que les visites sont, logiquement, une information de popularité). Quant aux sites et articles qui sont peu ou mal référencés, ils travaillent sur des statistiques tellement faibles qu'on est dans l'aléatoire pur (valeurs pas discrimantes, une visite un jour, zéro le lendemain, 3 le jour suivant). Le nombre d'entrées dans l'absolu doit donc être pris en compte, il permet d'avoir non seulement un fonctionnement quand les referers sont désactivés, mais en plus une valeur de base pour les articles à faibles visites (au moins, ça augmente de 1 ou 2 par jour).
De plus, les articles les plus "visités actuellement" ne sont pas forcément les plus référencés: sur uZine, l'article "Installer SPIP" est un des articles les plus visités (actuellement, pas seulement sur la durée), alors qu'il a un nombre de referers très faible. D'accord, c'est un exemple spécifique, mais c'est logique: certains articles sont visités parce qu'on navigue sur le site vers les articles "pertinents", mais ce ne sont pas forcément les articles référencés depuis l'extérieur (notamment sites à "dossiers" où un seul article est référencé, voir même l'entrée directe dans une rubrique, auquel cas avec les referers_articles on ne compte plus rien du tout).
while ($row = mysql_fetch_array($result)) {
$id_article = $row['id_article'];
$referers = $row['referers'];
$visites = $row['visites'];
$popularite = intval(10 * sqrt(($referers + 1) * $visites));
$popularite_update[$popularite][] = $id_article;
if ($max < $popularite) $max = $popularite;
}
Ensuite, le gain de popularite est obtenu en multipliant le nombre de sites-referers différents par le nombre d'entrées directes. Or, le nombre de sites-referers est extrêmement aléatoire, et puisque désormais on a un nombre d'entrées directes, ce nombre est beaucoup plus pertinent dans une optique de popularité (de plus, il dépend déjà pour un bonne part du nombre de sites-referers). En multipliant par le nombre de sites-referers, on obtient de plus une surpondération énorme des articles à mots-clés forts (sex, mp3) en provenance des moteurs (nombreux referers différents à très peu de visites), par rapport aux articles référencés "volontairement" par un nombre de sites eux-mêmes très fréquentés (peu de referers différents pour éventuellement le même nombre de visites). De plus, le nombre de sites-referers dépend du système utilisé sur le site réferant: un article référencé dans un article sous SPIP aura en gros un referer unique (car théoriquement une seule URL par article), alors qu'un article sous un autre système (daCode, Nuke) aura plusieurs referers identifiés pour un même lien (flagrant en ce moment sur l'article de Fil sur unicode; un article recevant 100 visites directes depuis un site sous SPIP (une seule URL) aura donc une popularité de 10*sqrt(100), et 100 visites directes depuis un site sous daCode (presque 10 URL différentes) aura un popularité de 10*sqrt(1000). Donc, le critère "visites" seul est plus pertinent; multiplier par le nombre de sites-referers est à la fois redondant et aléatoire.
if ($max < 100) $max = 100;
D'où sort cette valeur de 100??? Le système est conçu pour aller chercher des valeurs sur l'ensemble des visites, histoire de fabriquer une normalisation logique, et on sort une valeur absolue à partir de rien? Pour info, sur uZine, aujourd'hui, on obtient un $max de 5819. Et sur un site peu référencé, évidemment il ne sera pas anormal d'avoir aussi un $max inférieur à 100.
$query = "UPDATE spip_articles SET popularite = popularite + $popularite * 100 / $max ".
"WHERE id_article IN (".join(', ', $articles).")";
La modification de popularité est donc basée sur le calcul: $popularite * 100 / $popularite_maximale. (Mais c'est une série x_1 = x_0 + delta; pour simplifier à l'extrême, en considérant que la popularité est stable d'un jour à l'autre - même si elle varie beaucoup sur les périodes plus longues -, on obtient bien la popularité calculée précédemment, ramenée en pourcentage de la valeur maximale, mais amortie sur quelques jours.))
Très bien. Bon, toujours sur l'exemple hyper-vachement-spécifique d'uZine, j'obtiens, sur 503 articles calculés, 146 articles avec une modif de 0, 202 avec un modif de 1, et 70 avec une modif de 2. C'est-à-dire 418 articles sur 503 qui se voient modifier d'une valeur de 0, 1 ou 2. On obtient ainsi une popularite qui n'est pas du tout discriminante pour les 4/5 du site. Donc, il vaut mieux prévenir: la popularité ne sert à afficher que les 7 articles les plus populaires sur l'ensemble du site, mais faut surtout pas jouer avec sur des rubriques, parce que là ça ne donnera plus rien du tout; ni même sur des secteurs entiers si les visites du site sont déséquilibrées selon les secteurs.
Sur des sites faiblement référencés, vu qu'on a un $max qui est fixé arbitrairement à une valeur supérieure, on détruit encore plus la discrimination, vu que la modif de popularité maximale ne sera plus un pourcentage de la valeur max, mais sur bien plus (si le $max réel est 50, on "divise" les gains de popularité, déjà dérisoires pour la plupart des articles, par 2).
$query = "UPDATE spip_articles SET popularite = popularite * 100 / $max";
$result = spip_query($query);
Enfin on "normalise" à nouveau (histoire de ne pas obtenir de valeur supérieure à 100, c'est normal). $max étant la valeur maximale de popularité sur les articles. Or, chaque jour la valeur maximale (dès qu'un site est relativement référencé, donc qu'on ne recourt pas au $max=100) de popularité avant modif est 100%; le lendemain, on ajoute la nouvelle valeur calculée, et comme la plupart du temps le site le plus "populaire" le reste pendant plusieurs jours, c'est le même qui se voit attribuer 100+100, donc le $max pour la normalisation est 200 (en gros, sauf à imaginer que l'article ayant la plus grosse popularité change tous les jours, avec des changements de valeur énormes, et malgré l'amortissement du calcul par les referers sur 7 jours). Ce qui signifie qu'on divise simplement toutes les valeurs par deux.
Sur uZine, on obtient donc, sur 503 articles, 418 articles dont la popularité déjà faible (0,1,2) est divisée par deux; ça devient vraiment plus du tout discriminant, avec des suites qui tendent, pour les 4/5 des articles, vers les valeurs 0 ou 1.
Et là-dessus on fait le ménage:
$query = "DELETE FROM $table WHERE date < DATE_SUB(NOW(),INTERVAL 7 DAY) OR visites <= $visites_min";
J'avais mis un AND, et non un OR. Puisqu'ici, on détruit purement et simplement les referers des articles à faible traffic, et donc le calcul de popularité, puisqu'on ne laisse même pas le temps d'accumuler sur 7 jours au moins quelques "petits" referers. Et au bout de 7 jours on efface tout, y compris le referer énorme qui alimente en visites énormes tous les jours le même article, mais depuis une semaine (il recommence à zéro du jour au lendemain sans aucune modification réelle de l'activité de l'article).
L'ensemble est incohérent de bout de bout. Sur les sites à faible traffic, peu référencés, les valeurs seront tout bonnement aléatoires. Les referers étant désactivés, on n'a plus rien non plus. Sur des sites au traffic réparti de manière très hétérogène (soit à cause de quelques articles receuillant le plus de traffic direct, soit parce qu'il y a dossiers, avec un article servant de porte d'entrée), on obtient des résultats uniquement pour une poignée d'articles, les résultats suivants sont tellement peu disciminants que ça n'a aucun sens - ça, on me croit ou non, mais sur tous les sites les visites sont très hétérogènes. En revanche, ça oui, sur des gros sites à très fort traffic, à la structure très homogène (pas d'articles vraiment "en vedette" référencés par un gros site), sur une durée de 10 jours à la fin des vacances, certainement ça a une chance de fournir un résultat.
ARNO*