Détecter un robot avec CakePHP 2.x

Il peut être parfois intéressant de changer le comportement d’une page si c’est un robot qui est en train de la visiter. On peut ainsi éviter la génération de panier dans une boutique ou des Tokens sur un formulaire de contact. Surtout si votre site contient plein de formulaires de contacts 🙂

CakePhp dans sa version 2 intègre un nouvel RequestHandler.  De base, cet Objet Request intègre différentes détections classiques comme l’utilisation d’un mobile, d’une connexion SSL, requêtes POST ou GET, … Mais on peut aussi lui ajouter nos propres règles.

Tout d’abord on va utiliser un modèle Bot dont la table contiendra les robots et user_agent.

Le fichier SQL pour la table bots : Table des user_agent des principaux robots

Dans votre AppController::beforeFilter(), insérez le code suivant, où vous voulez

  /*
   * table bot
   */
   $this->loadModel('Bot');
   $bots = $this->Bot->find('all', array('fields' => 'agent', 'conditions' => 'is_active = 1'));
   $bots = Set::extract($bots, '{n}.Bot');
   $patternBot = array();
   foreach ($bots as $data) {
     $patternBot[] = str_replace('\*', '.*?', preg_quote($data['agent'], '#'));
   }
   $this->request->addDetector('bot', array('env' => 'HTTP_USER_AGENT', 'pattern' => '`' . implode('|', $patternBot) . '`'));

Point par point :

  • On charge le model ‘Bot’ pour pouvoir accéder à celui-ci
  • On récupère tous les user_agents des robots actifs
  • Un passage dans Set::extract pour nettoyer le résultat
  • On quote les agent pour que ça puisse passer dans le preg_match()
  • et on fabrique une énorme expression régulière que l’on transmet au RequestHandler

Nous avons donc maintenant un nouveau detecteur dans le RequestHandler et on peut utiliser dans n’importe quel controller :

$this->request->is('bot');

Et voilà 🙂

Pour plus de rapidité, il est conseillé d’utiliser le Cache pour les résultats.

    /*
     * table bot
     */
    $patternBot = Cache::read('pattern_bot');
    if (!$patternBot) {
      $this->loadModel('Bot');
      $bots = $this->Bot->find('all', array('fields' => 'agent', 'conditions' => 'is_active = 1'));
      $bots = Set::extract($bots, '{n}.Bot');
      $patternBot = array();
      foreach ($bots as $data) {
        $patternBot[] = str_replace('\*', '.*?', preg_quote($data['agent'], '#'));
      }
      Cache::write('pattern_bot', $patternBot);
    }
    $this->request->addDetector('bot', array('env' => 'HTTP_USER_AGENT', 'pattern' => '`' . implode('|', $patternBot) . '`'));

Prochaine étape, détecter si le user agent contient « Bot, Spider, Crawler, Slurp, … » et qu’il n’est pas détecté comme un robot pour l’ajouter à la table automatiquement avec un statut 0. Restera à passer changer les statuts si c’est vraiment des robots et votre table s’auto-alimente, mais ce sera pour plus tard.

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Time limit is exhausted. Please reload CAPTCHA.