Ne peut-on pas imaginer un "piège" à robots. J'en ai codé un (le code est en ligne sur le site).
Le principe est de récupérer l'IP sur une page cachée (lien gif transparent dans le coin de la page)
=> Aucun humain ne visitera cette page (donc on a une liste des robots).
Ensuite, pour savoir si le robot est "clean" j'ai imaginé un piège en utilisant 2 pages dissimulées dont une seule est interdite dans le fichier robots.txt.
Dans le cas ou aucune de ces 2 pages n'est visitée et que le nombre de requetes provenant d'une meme IP dans un espace de temps donné est superieur x, j'estime qu'il s'agit d'un mauvais robot... (dans ce cas, je compte le nombre de requetes sur 5mn par exemple, si le nombre est superieur a 500, il ne s'agit pas d'un humain... si le robot ne visite pas la page dissimulée autorisée, il s'agit donc d'un mauvais robot)
Si le robot visite une page interdite par mon fichier robot, il s'agit également d'un mauvais robot....
Le seul probleme c'est que si un "mauvais" robot se comporte comme un "bon" robot (qu'il suit les directives du fichier robots.txt), je ne peux pas le détecter...
Une petite chose:
remplace : strpos($IPtab[$t], $_SERVER['REMOTE_ADDR'])
par : strpos($_SERVER['REMOTE_ADDR'],$IPtab[$t])
(Voila pourquoi ca marche pas amery...)
oups, effectivement
faut m'excuser, je croise tous le temps des coders
qui ne se donne jamais la peine d'aller voir le manuel de php,
que j'ai pris de mauvaises habitudes.
@ cpp4ever... oui merci ça fait un bail que je connais in_array()... lol... regarde bien la source avant de faire ce genre de réflection... tu remarquera que le tableau $ipTable contiens des plages d'ip et non pas que des ip complètes... et dans ce cas in_array() ne sert strictement à rien... à la limite preg_grep() aurait fait l'affaire mais perso je préfère la boucle... .. .
@kankrelune : Bon sang de bon soir... Merci... Je ne savais pas exactement étaient évaluées les conditions multiples par if... J'ai fait un test pour vérifier tes dires (c'est pas que j'ai pas confiance, mais là, au moins, je peux me permettre de l'affirmer à mon tour si besoin, puisque j'ai expérimenté).
Donc merci pour ces petits détails qui enrichissent tous les jours ma culture de geek...
"Je conseillerais plutôt de vérifier l'user_agent qui, lui, est toujours défini par les bots des moteurs de recherche."
>> Si c'est bien défini par tous les bots alors oui, mais j'avais lu que c'était pas toujours le cas...
@ neigedhiver... non car la première instruction de la condition étant fausse la seconde n'est pas vérifiée... .. .
@ Astalavista... pas forcement... foreach travail sur une copie du tableau, for non... après c'est une question de perf et de façon de faire... pour gagner en rapidité j'aurais tendance à faire...
MadM@tt, ta méthode est lourde et pas très fiable (je ne pense pas que la liste des ips soit à jour).
Je conseillerais plutôt de vérifier l'user_agent qui, lui, est toujours défini par les bots des moteurs de recherche.
Voilà ce que je fais :
Là aussi, syntaxiquement, tu vérifies si une variable potentiellement non instanciée est vide... Le fait de vérifier qu'elle existe ne la fait pas exister si tel n'est pas le cas...
Puor bien faire, il faudrait alors faire un autre test avec empty() dans le bloc if.
Non ?
Je peux me permettre une remarque ?
empty($var) retourne true si :
- la variable $var est vide ( $var = '' )
- la variable $var n'est pas définie
Il me semble donc que le test isset($_SERVER['REMOTE_ADDR']) est inutile : si la variable $_SERVER['REMOTE_ADDR'] n'est pas vide, alors elle est définie.
pas exactement... en fait $i++ c'est de la post incrémentassion et ++$i de la pré incrementassion... .. .
Dans le premier cas l'instruction, si instruction il y a, est exécutée puis la variable est incrémentée de 1... dans le second cas la variable est incrémentée puis l'instruction est exécutée... exemple...
Hormis cette petite différence la pré incrémentassion est légèrement plus rapide que la post incrémentassion car en pré inc php ne se pose pas de question et incrémente directement la variable alors qu'en post inc php garde en mémoire qu'il doit incrémenter la variable après avoir exécuté l'instruction en cours... .. . ;o)
Je me rends compte que j'ai pas écrit du tout ce que je voulais dire... Je suis fatigué, j'ai plus l'habitude de bosser.
Euh donc je voulais dire que c'est sympa quand les gens prennent bien les commentaires et s'en servent de manière constructive, sans se vexer, etc.
Mais je crois que tu avais compris...
Bonne continuation.
Histoire d'optimiser encore un peu... perso je ne suis pas fan de cette méthode car si le bot à changé d'adresse ip ou s'il n'est pas répertorié ton script ne sert à rien... le mieux serait de faire un lien caché vers une page ou de compter le temps entre chaque ouverture de page et de stocker l'ip s'il sagit d'un bot... .. .
Je voit que j'ai aidé :), je te remercie neigedhiver d'avoir affirmer ce que j'ai marqué ...
Ha oui, il y a encore une petite erreur :
for($t = 1; $t <= $max; $t = $t++)
S'utilise plutôt comme ca :
for($t = 1; $t <= $max; $t++)
ton count doit s'écrire en minuscule
à mon avis, le foreach est un peut plus adapté.
Si un jour tu supprime la clef 19 (par exemple), il faudra changer toutes tes autres clef.
Mais bon, si tu insiste pour utiliser ton for, ajoute tes IP de cette façon :
$IPtab[] = '66.249.';
$IPtab[] = '207.68.146.';
L'ajout se fera à la suite, et 0 par défaut.
Non non, strpos() est une très bonne solution, si on ne se contente pas de vérifier que la chaine a été trouvée, mais si on vérifie aussi la position (valeur retournée par strpos() justement !). En plus, c'est plus court :
if (strpos($IPtab[$t], $IP) === 0)
{
return true;
}
Return va automatiquement sortir de la fonction et retourner true quand la chaine est trouvée.
Par contre je me pose la question concernant la recherche de l'ip dans l'ip du visiteur :
// Récupère la partie gauche de la chaine
$left = substr($IP, 0, strlen($IPtab[$t]));
if ($left == $IPtab[$t]) {
$Return = true;
break;
}
Je trouve ça bete de faire un substr à chaque boucle, mais comment faire une comparaison de chaine en partant à gauche de la chaine ?
(car les adresses IP du tableau sont de la form 168.69. mais avec un strpos il peut me le trouver dans une adresse de la forme 145.168.69....)
Je ne crois pas que foreach() soit tellement plus rapide que for().
Par contre, la syntaxe de ta boucle est à proscrire à tout prix, parce que tu utilises la fonction count à chaque itération, ce qui est très couteux en performances.
Dans ton cas, foreach() est plus adapté car sa syntaxe est plus claire et tout aussi efficace.
Pour garder for() il faudrait faire comme ceci :
$nb = count($IPtab);
for($t = 1; $t <= $nb; $t++) {
La syntaxe $t++ est équivalente à $t = $t +1, mais plus courte, tout aussi claire et plus performante puisqu'elle ne fait appel qu'une seule fois à la variable (qui est lue chaque fois dans la pile, ne pas l'oublier) et qu'elle est optimisée pour cette opération...
Merci pour le commentaire, par contre j'aurais besoin d'un peu d'explication :
pourquoi privilegier foreach plutot que for ? c'est plus rapide ?
Et de ton code j'en déduis que l'instruction "return" fait terminer la fonction ? (ce qui effectivement est bien mieux que ce que j'ai fait)
Pour le fichier, bonne idée, mais si ce code est appelé à chaque page vue ça risque de faire perdre beaucoup de temps s'il faut que j'ouvre le fichier à chaque fois, et que je parse le contenu.
Pas mal, mais :
Utilise plutot un fichier pour ta liste d'adresses, et pour vérifier utilse plûtot ceci :
$IP = $REMOTE_ADDR;
// Vérifie chaque adresse
foreach( $IPtab as $IP_Rechercher)
if((strrpos($IP, $IP_Rechercher) === 0)return FALSE;
return TRUE;
28 mars 2010 à 23:32
$IPtab[] = '204.236.235.245'; //Alexa
$IPtab[] = '66.235.112.'; //Ask Jeeves/Teoma
$IPtab[] = '66.235.124.';
$IPtab[] = '220.181.'; //Baiduspider
$IPtab[] = '61.135.168.';
$IPtab[] = '208.115.111.242'; //DotBot
$IPtab[] = '88.131.106.'; //Entireweb
$IPtab[] = '193.47.80.36'; //Exabot
$IPtab[] = '66.249.71.75'; //Google-Adsense
$IPtab[] = '212.117.183.169'; //GoogleBot
$IPtab[] = '207.46.'; //MSN Bot
$IPtab[] = '65.55.';
$IPtab[] = '66.219.58.42'; //Metadata Labs
$IPtab[] = '38.99.97.118'; //ScoutJet
$IPtab[] = '67.195.110.163'; //Slurp Inktomi (Yahoo)
$IPtab[] = '72.30.161.225';
$IPtab[] = '81.19.66.89'; //StackRambler
$IPtab[] = '67.218.116.162'; //Twiceler
$IPtab[] = '193.252.118.'; //VoilaBot
$IPtab[] = '69.41.173.145';
$IPtab[] = '81.52.143.';
$IPtab[] = '77.88.31.247'; //Yandex
$IPtab[] = '119.235.237.'; //Yeti
10 oct. 2008 à 12:20
Le principe est de récupérer l'IP sur une page cachée (lien gif transparent dans le coin de la page)
=> Aucun humain ne visitera cette page (donc on a une liste des robots).
Ensuite, pour savoir si le robot est "clean" j'ai imaginé un piège en utilisant 2 pages dissimulées dont une seule est interdite dans le fichier robots.txt.
Dans le cas ou aucune de ces 2 pages n'est visitée et que le nombre de requetes provenant d'une meme IP dans un espace de temps donné est superieur x, j'estime qu'il s'agit d'un mauvais robot... (dans ce cas, je compte le nombre de requetes sur 5mn par exemple, si le nombre est superieur a 500, il ne s'agit pas d'un humain... si le robot ne visite pas la page dissimulée autorisée, il s'agit donc d'un mauvais robot)
Si le robot visite une page interdite par mon fichier robot, il s'agit également d'un mauvais robot....
Le seul probleme c'est que si un "mauvais" robot se comporte comme un "bon" robot (qu'il suit les directives du fichier robots.txt), je ne peux pas le détecter...
10 juil. 2007 à 19:20
10 juil. 2007 à 15:50
Simpa la source ;)
(tu aurais pus mettre tout les ips dans un fichier aussi )
@++
29 juin 2007 à 15:12
Et merci pour ta liste d'IP