Le but du projet est d'implémenter un robot de recherche Web de type Google simplifié. Le robot comporte trois parties : (1) le crawler(araignée) qui explore les pages HTML du WEB afin de constituer (2) la base de données liant les URI aux mots qui les décrivent et (3) le module d'interrogation qui cherche dans la base des mots et affiche les URIs correspondants.
Le projet est constitué de plusieurs répertoires :
Les Pages du projet (dans les repertoires HTML et CGI-BIN) :
Le projet a été réalisé avec le langage java, HTML, PHP et une base de données MySql.
Le crawler a été écrit avec le logiciel EasyPHP 1.7 sur Windows qui regroupe :
3) Execution :
Il n'y a pas de répertoire MAKEFILE. Pour la compilation du projet,
il suffit d'aller dans le répertoire SRC, la où se trouve les fichiers java.
La commande : javac *.java permettra la compilation.
Pour pouvoir lancer le crawler, il suffira de faire la commande suivante :
java MonCrawler < fichier de configuration > <--options>
Remarque:
Je n'ai pas totalement fini le projet :
les options --img et --mail ont été réalisé mais elles posent certains problèmes lors du parcours.
L'option --cond n'a quand à elle pas été réalisé. Seul l'option --init fonctionne correctement.
Autre remarque importante:
Il est important que lors de la consultation ou de la modification du fichier de configuration à l'aide des pages dans le répertoire CGI-BIN, la répartition des répertoires ne soient pas changés.
Cela parce que lors de la consultation ou de la modification des configurations, on utilise un chemin relatif pour acceder au fichier de configuration : ../SRC/crawler.conf.
Nous allons expliquer ici le fonctionnement de notre crawler.
Le crawler contient 4 parties :
1) L'initialisation :
Notre programme va tout d'abord vérifier que les arguments entrés par l'utilisateur sont corrects.
L'utilisateur doit impérativement mettre en argument le fichier de configuration.
Il peut aussi ajouter les options souhaitées. Comme dit précedemment, l'option "--cond" n'a pas été implémentée.
De plus, les options "--img" et "--mail" posent certains problèmes que je n'ai pas réussi à régler.
Le crawler va lire les informations contenues dans le fichier de configuration.
Il va ensuite créer le fichier de journalisation "crawler.log".
Le lancement du parsage commence par l'appel à la fonction "Exlpore()".
2) Les classes de vecteurs :
Nous avons défini 3 vecteurs :
1)TabURI tab;
2)TabPageAPaser vecteurLiens;
3)TabLiensVisites PageDejaVisitee;
1) tab va contenir toutes les URI parcourues. Il aura, pour chaque URI, 3 informations ( voir la classe AdresseURI ):
2) vecteurLiens va contenir les adresses des pages parsées. Au fur et à mesure du parsage, des pages vous être ajoutées et d'autres retirer du vecteur. Ce vecteur va nous permettre de prendre en compte la profondeur du parcours (voir fichier de configuration) et donc de nous arrêter à la profondeur souhaitée.
3) PageDejaVisitee va contenir les adresses des pages parsées. Ce vecteur va être utilisé pour nous permettre d'éviter de parser une page déjà visitée.
3) Le parcours des pages HTML :
Le Crawler va commencer par parcourir la racine à l’aide de la classe « CrawlerCallbackHandler » (voir fonction Explore()).
//Parcours de la racine
CrawlerCallbackHandler handler = new CrawlerCallbackHandler(tab,vecteurLiens,PageDejaVisitee,urlChemin,optionImage,optionMail);
new ParserDelegator().parse(rdr, handler, true);
« CrawlerCallbackHandler » est une classe fille de HTMLEditorKit.ParserCallback qui va redéfinir les méthodes handleStartTag(), handleEndTag(), handleSimpleTag() et handleText().
Ces méthodes servent au parcourt d’une page HTML. Elles vont permettre d'insérer, dans les différents vecteurs définis plus haut, les informations sur les pages visitées.
Les informations receuillies sur le vecteur "TabURI tab" vont être insérées dans la base de données et dans le fichier de journalisation "crawler.log".
On fait appel maintenant à la fonction récursive "private void parcoursLargeur()".
Cette fonction va effectuer les même opérations que la fonction "Explore()".
Elle va simplement parser la première de page qui se trouve dans "vecteurLiens".
Elle fera appel à la classe « CrawlerCallbackHandler » comme pour la fonction "Explore()".
Puis elle insérera les informations recueillies dans la base de données et dans le fichier de journalisation à partir des vecteurs.
Pour finir, elle fera un appel à elle-même, c'est-à-dire un appel récursif.
La difficulté ici sera de faire en sorte que la parsage s'arrête à la profondeur décrite dans le fichier de configuration.
Comment vecteurLiens permet le parcours en largeur sur une profondeur p :
En faite, voila comment on va pouvoir faire un parcours en largeur sur une profondeur p :
A l'entrer de la fonction "Explore()", vecteurLiens est vide. On va insérer la racine dans ce vecteur.
Puis on insère le caractère "*". Ce caractère symbolise le fait qu'on change de profondeur.
Ensuite on fait appel à la fonction "CrawlerCallbackHandler (TabURI tab, TabPageAPaser vecteurLiens, TabLiensVisites PageDejaVisitee, String cheminRacine, boolean optionImage, boolean optionMail)" qui va parser la page racine.
Elle va insérer les pages fils de la racine dans vecteurLiens.
On entre maintenant dans la fonction de parcours récursive "parcoursLargeur()". Cette fonction va supprimer le premier élément de vecteurLiens (c'est-à-dire la racine). Le premier élément du vecteur est maintenant "*". Le vecteur contient aussi tous les fils de la racine. On va donc baisser de 1 la variable de profondeur et insérer l'élément "*" pour signifier que les prochains éléments qui seront ajoutés auront une profondeur égale à +1 celle de leur prédécesseurs. On va ensuite parser tous liens contenus dans le vecteur jusqu'à rencontrer le symbole "*". La fonction récursive "parcoursLargeur()" s'arrête lorsque la variable profondeur est inférieure à 0.
Cela fonctionne car on sait que toutes les pages d'une profondeur p se trouvent à la suite et sont terminé par l'élément "*". A chaque fois que l'on va parser une page de la profondeur p, on va ajouter ces liens derrière le symbole "*" pour dire que leur profondeur est supérieure de 1. Lorsque l'on aura visité la dernière page de profondeur p, on ajoutera le symbole "*" derrière ces liens fils. On pourra alors commencer le parsage des pages de profondeur p+1 et ajouter leurs liens fils derrière le dernier symbole "*" ajouté. On répète l'opération jusqu'à ce que la profondeur soit atteinte.
4) L'enregistrement des informations :
Après le parsage d'une page HTML, le crawler enregistre, dans la base, les informations (mots clés, type) des liens de cette page.
Le crawler enregistre toutes les informations dans le fichier de journalisation à l'aide des méthodes "FichierJournalisation(String msg)" et "AfficheFichierJournalisation()" (voir classe MonCrawler.java).
Elle sert de tampon de communication entre le crawler et le module d’interrogation.
Le crawler enrichit cette BD avec les informations recueillies sur les URIs explorées.
Nous avons besoin de 3 tables pour notre projet :
Nous allons décrire les principales méthodes pour la gestion de la base de données :
Voici comment se présente la fonction "insertionBDD()" ( voir MonCrawler.java ):
//Fonction qui gere les insertions dans la base de données. public void insertionBDD() { int idURI, idMot; String leMotCourant = null; Vector lesMots=null; int taille,i; Object obj; AdresseURI adresse; try { taille = tab.size(); //Pour chaque URI contenu dans "tab", on insere ses //informations dans la base de données. for (i=0 ; iDonc pour chaque page parsé, on va faire : 1 accès pour insérer l'URI, n accès ( avec n inférieur aux nombres de pages parséss pour l'option --init) pour chercher l'identifiant de l'URI insérée, puis pour chaque mot clé d'une URI on fait un accès ( p accès ), puis on recherche l'identifiant du mot inséré ( maximun n.p accès ) et pour finir on fait un accès pour faire le lien entre les 2 tables.
On peut en conclure que les accès à la base pour le parsage des pages HTML est de l'ordre de n*n*p au maximum.