Les bots PHP : Première partie

Avant propos :

Ici commence une série de tutoriels sur les bots en PHP. Au court cette initiation, je vous présenterai les connaissances et techniques nécessaires au développement de ces "petits" scripts bien utiles qui èrrent sur la toile. Bonne lecture à tous.

Sommaire :

- Introduction
- - Qu'est-ce qu'un bot ?
- - L'architecture client-serveur sur le web
- - Pourquoi PHP ?
- Réchauffons les bases à petit feu
- - Commençons par récuperer une page
- Conclusion

Introduction :

Qu'est-ce qu'un bot ?

Avant tout, pour fixer tout le monde, définissons ce qu'est un bot.
Il s'agit d'un agent qui se connecte a des serveurs et interagit avec eux comme s'il était un programme client utilisé par un humain. Cela explique le terme "bot" qui est la contraction du mot "robot". Il effectue le plus souvent des tâches répétitives (automatisations) ou des tâches dont la réactivité est un facteur clé de la réussite (jeux, enchères).
Les bots les plus connus sont les crawlers, comprennez les robots d'indexation, qui indexent chaque page qu'ils trouvent pour les reporter aux grands moteurs de recherche tel Google.
Dans nos cas, nous nous consacrerons plus au bots d'automatisations dans le domaine des jeux onlines par exemple.

L'architecture client-serveur sur le web

Avant d'aller plus loin, rappelons ce qu'il se passe lorsque l'on clique sur un lien hypertext.
Armé de votre browser favoris, qui joue ici le rôle de client, vous envoyez une requête au serveur web contenant les pages qui vous intéressent (on occultera à ce stade toutes les choses du genre résolution de DNS, redirections). Ce dernier analyse la requete et vous renvoie une réponse avec votre page et diverses informations (dans le meilleurs des cas, on supposera que le serveur est en état de marche ;)).

requete

Voilà pour les cas d'utilsations habituels. Maintenant, notre but sera de remplacer l'humain que vous êtes avec votre browser, par un programme qui envoyera et recevra des messages d'un serveur web.

Pourquoi PHP ?

C'est une question que certains se posent peut-être. On aurait très bien pu faire un bot en C ou même Java..
Premièrement, comme le C ou le Java, PHP possède tout ce qu'un bot requière (alors pourquoi s'en priver ? :=). De plus, la gestion des flux est relativement aisée dans ce langage. On trouve aussi de nombreuses extensions ou scripts utiles pour la suite (nous y reviendront en temps voulu) qui sont dus à l'orientation Web du langage.


Réchauffons les bases à petit feu :

Commençons par récuperer une page

Puisqu'il faut bien commencer par quelque chose, j'ai pris ce qui me semblait le plus logique. Il s'agit de l'opération principale à la base du bot : récupérer une page Web. Comme nous l'avons vu, il faut envoyer une requete à un serveur puis écouter sa réponse. Deux méthodes s'ouvrent t'a nous pour ca :

  • l'ancienne école avec gestion de flux et forge de requete (on a dit "old school" :s)
  • l'utilisation de la bibliothèque cURL

L'ancienne école :
Pour ceux qui veulent vraiment comprendre comment se passent les choses, je conseille cette méthode. De plus, elle permet vraiment de contrôler tous les mécanismes et de les personnaliser au besoin (ce qui va s'avérer utile pour la suite =D).
Commençons par créer une connexion par socket au serveur intéressé :

  1. $sock = fsockopen("www.leserveur.com");

Voilà qui est fait. Maintenant, il va nous falloir envoyer une requête.
La question n'est pas comment (fwrite() est là pour ça ;)) mais plutôt laquelle ! Et là, ca se complique. Il nous faut forger une requête HTTP.
Qu'a celà ne tienne, comme nous commençons, nous ferons quelque chose de très simple. Supposons que l'on veuille récupérer la page "www.leserveur.com/lapage.php", voici quelle en serait la requête :

  1. GET /lapage.php HTTP/1.1
  2. Host: www.leserveur.com
  3.  
  4.  

Il s'agit de la requête minimale mais néanmoins fonctionnelle pour récupérer la page (nottez qu'elle s'avèrera très insufisante par la suite :(). Voyons de suite que cela donne pour l'envoyer via notre socket :

  1. $req = "GET /lapage.php HTTP/1.1\r\n";
  2. $req.= "Host: www.duels.com\r\n\r\n";
  3. fwrite($sock, $req);

Nottez ici le double retour à la ligne qui signifie que la requête est terminée. Son oubli est source d'erreurs très prise de tête.
A ce moment, nous venons d'envoyer notre requête. Récupèrons maintenant la réponse de la part du serveur. Pour se faire, utilise fgets() :

  1. $content = "";
  2. while (!feof($sock)) {
  3.     $content.= fgets($sock, 128);
  4. }

Vous pouvez tester ces petits bouts de code et vous verrez que le corps de la page en question se trouve dans la variable $content ainsi que d'autres informations (que nous traiteront par la suite).

Résumons cette méthode en une fonction qui retourne la réponse du serveur ou false en cas d'erreur :

  1. function get_page($url) {
  2.    
  3.     // Analyse l'url
  4.     $url = parse_url($url);
  5.     $serveur = $url['host'];
  6.     $page = $url['path'];
  7.    
  8.     // Ouvre le socket
  9.     $sock = fsockopen($serveur, 80, $errno, $errstr, 30);
  10.     if (!$sock) {
  11.         echo "Erreur : $errstr ($errno)";
  12.         return FALSE;
  13.     }
  14.    
  15.     // Forge la requête
  16.     $req = "GET $page HTTP/1.1\r\n";
  17.     $req.= "Host: $serveur\r\n\r\n";
  18.    
  19.     // Envoit la requète et récupère la réponse
  20.     fwrite($sock, $req);
  21.     $content = "";
  22.     while (!feof($sock)) {
  23.         $content.= fgets($sock, 128);
  24.     }
  25.    
  26.     // Ferme le socket
  27.     fclose($sock);
  28.    
  29.     // Retourne la réponse du serveur
  30.     return $content;
  31. }
TéléchargerTélécharger source5.php

Nottez que cette fonction n'est qu'un très simple extrait de la fonction finale (requêtes complexes, méthode POST avec envoi de données, parsing des headers HTTP, décryption des réponses serveur sont au programme ! :D).

L'utilisation de la bibliothèque cURL :
Avant toutes choses, sachez que vous devez avoir installé et configurer libcurl pour PHP. Pour vérifier que c'est bien le cas, un simple phpinfo() vous le confirmera. Dans le cas contraire, repportez-vous à la référence cURL sur php.net.

phpinfo()

Commençons par créer une session cURL. Pour se faire, on utilise la fonction curl_init() comme suit :

  1. $ch = curl_init();

Il nous faut maintenant configurer cette session, puis l'exécuter par la suite. Voyons comment faire à l'aide de curl_setopt() :

  1. curl_setopt($ch, CURLOPT_URL, "http://www.leserveur.com/lapage.hmtl");
  2. curl_setopt($ch, CURLOPT_RETURNTRANSFERT, TRUE);

C'est le minimum dont nous avons besoin. Comme vous l'avez devinez, la première ligne précise la page à récuperer et la seconde précise qu'il nous faut récupérer le contenu de la page en retour de l'exécution de la session. Si vous le ne faites pas, vous appellerez la page et l'enverrez directement en sortie. Je vous invite à passer faire une tour sur la documentation de PHP pour voir toutes les options proposées.
Maintenant que notre session est configurée, nous pouvons l'exécuter via curl_exec() :

  1. $content = curl_exec($ch);

Vous récupérez alors le contenu de la page dans la variable $content.
Note : pour une question de propreté du code et d'optimisation, pensez à libérer les ressouces cURL lorsque vous n'en avez plus besoin avec curl_close().

  1. curl_close($ch);

Résumons cette deuxième méthode en une fonction qui, comme la précédente, retourne la réponse du serveur ou false en cas d'erreur :

  1. function get_page($url) {
  2.  
  3.     // Initialise une session cURL
  4.     $ch = curl_init();
  5.  
  6.     // Configure la session
  7.     curl_setopt($ch, CURLOPT_URL, $url);
  8.     curl_setopt($ch, CURLOPT_RETURNTRANSFERT, TRUE);
  9.  
  10.     // Exécute la session
  11.     $content = curl_exec($ch);
  12.  
  13.     // Libère les ressources
  14.     curl_close($ch);
  15.  
  16.     // Renvoit le contenu de la page
  17.     return $content;
  18. }
TéléchargerTélécharger source10.php

Cette fonction-ci est aussi très simple par rapport à ce que permet de faire cURL (envoi de données via POST, gestion des cookies et session, SSL, etc).


Conclusion :

Comme vous pouvez le voir, cURL semble beaucoup plus propre à utiliser et nous libère de toute la gestion de flux. De plus par la suite, il s'avèrera plus facile d'utiliser cURL pour les fonctionnalités avancées.
A l'opposé, certains le préfèrerons peut-être les sockets car elles vous laissent un contrôle total et une possibilité d'agir à n'importe quel moment. Je vous laisse choisir votre méthode.
La partie suivante de ce tutoriel sera consacrée aux princpales techniques et besoins d'une méthode comme de l'autre, ainsi qu'à leurs équivalents dans la méthode opposée. Wait & see ! ;)

 
 
Admin