Rapport_fin

publicité
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
ENST de Bretagne
Technopôle Brest-Iroise
29280 PLOUZANÉ
Méta-calendrier automatique pour portail www
Projet d’ingénierie
Isabelle KERVELLA
Mastère ISIC (Ingénierie des Systèmes Informatiques Communicants)
Soutenue le 21 mars 2002
Encadrant : Ronan KERYELL
1
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Résumé
L’objet de ce projet est de développer un outil qui collecte automatiquement des données dans des
sites publiés sur Internet et les rassemble dans un portail. Si le format HTML est parfaitement adapté
à la présentation de documents simples sur Internet et à la navigation entre les pages, il n’offre pas
une présentation structurée des données. Mélangeant le fond, la forme et les données, il n’est pas
aisé d’extraire l’information utile. Le travail réalisé dans le cadre de ce projet montre que l’utilisation
d’un wrappeur pour traduire un document non structuré dans un format XML, puis d’un parseur pour
extraire l’information, constitue une solution à ce problème.
Mots clés : HTML, extraction des données, wrapping, XML, parsing, API JAXP
2
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Table des matières
1
CONTEXTE .................................................................................................................................................. 4
1.1
COMPREHENSION DU BESOIN ................................................................................................................... 4
1.1.1 Analyse des sources, détection de l’information utile et extraction des données ................................ 5
1.1.2 Stockage des données .......................................................................................................................... 5
1.1.3 Nettoyage des données ........................................................................................................................ 5
1.1.4 Représentation visuelle des données ................................................................................................... 6
1.1.5 Paramétrage de la collecte / administration ....................................................................................... 6
1.2
2
ANALYSE FONCTIONNELLE ...................................................................................................................... 6
SOLUTIONS TECHNIQUES PROPOSEES ............................................................................................. 8
2.1
ANALYSE DE LA SOURCE, DETECTION DE L’INFORMATION UTILE ET DEFINITION D’UN FORMAT UNIFIE ... 9
2.1.1 Site analysé ......................................................................................................................................... 9
2.1.2 Détection de l’information utile, écriture du fichier de description .................................................... 9
2.1.3 Récupération de l’information utile dans un fichier au format XML ................................................ 11
2.2
LE PARSING ............................................................................................................................................ 12
2.2.1 Les APIs des parseurs ....................................................................................................................... 13
2.2.2 Développement du parseur en Java .................................................................................................. 14
3
CONCLUSION............................................................................................................................................ 16
4
BIBLIOGRAPHIE ...................................................................................................................................... 17
Table des figures
Figure 1 : schéma des principales étapes du projet ................................................................................................ 6
Figure 2 : liste des événements, classés par date, du site http://www.bzh5.com/gouel/degemer.php ................... 10
Figure 3 : Structure du calendrier ........................................................................................................................ 11
Figure 4 : l’information utile est recueillie dans un fichier XML ......................................................................... 12
Figure 5 : rôle d’un parseur XML & API DOM ................................................................................................... 13
Table des annexes
ANNEXE 1 ............................................................................................................................................................ 18
ANNEXE 2 ............................................................................................................................................................ 23
ANNEXE 3 ............................................................................................................................................................ 29
3
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Partie 1
1 Contexte
Le site trad.org est un portail de musique traditionnelle. La rubrique Bals & Concerts a pour vocation
d’informer des principaux événements folkloriques. Dans sa version actuelle, la rubrique est
constituée de liens hypertextes qui pointent vers des calendriers présentés dans des sites Internet
d’événements. Les nombreuses sources d’informations et la très grande disparité de ces informations
rendent difficile la recherche de données précises.
L’objet de ce projet est d’offrir une vue globale et à jour de ces informations, en développant pour ce
portail, un calendrier rassemblant les événements de l’ensemble des sites cibles. Le projet ne trouve
tout son sens que s’il permet l’extraction et la mise en forme automatiques des données. L’objectif de
ce travail est donc de trouver des solutions pour extraire l’information utile des différents sites Internet,
la stocker et la représenter visuellement sous la forme d’un calendrier sur le portail trad.org. La
principale difficulté est bien sûr de collecter des données hétérogènes de manière correcte et
cohérente.
1.1
Compréhension du besoin
Ce projet couvre plusieurs aspects, détaillés ci-après :

l’extraction des données

le stockage des données

le nettoyage des données

la représentation visuelle des données

le paramétrage de la collecte / l’administration
4
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
1.1.1 Analyse des sources, détection de l’information utile et extraction des données
Les données sont extraites de sites Internet (protocole http). Le fond et le format des données ne
sont soumis à aucune norme. Ils diffèrent selon la source d’information et ne présentent pas de
stabilité dans le temps. L’extraction des données inclut plusieurs étapes :
 L’analyse de la source (format HTML)
 La détection de l’information utile
 La définition d’un fichier de description propre à la source analysée
 La définition d’un format unifié pour toutes les données à collecter
 Le wrapping
 Le parsing
Elle implique également de tenir compte de différents paramètres :
 Le type de source (page HTML statique, résultat d’une requête)
 Les racines de l’information (adresse du site distant et protocole utilisé)
 Les caractéristiques de la connexion (port pour le protocole utilisé, proxy, firewall, login, mot
de passe, …)
 Le paramétrage de l’extraction : périodicité, granularité (incrémentale ou complète),
chargement des données (en ligne, hors ligne), …
1.1.2 Stockage des données
Deux modes de stockage peuvent être envisagés :
 Le stockage dans une base de données relationnelle (MySQL, …)
 Le stockage dans une base de données XML
1.1.3 Nettoyage des données
Le mécanisme de nettoyage des données couvre :
 L’identification des doublons grâce à la corrélation des calendriers
 La détection des annulations
 La détection des données obsolètes
5
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
1.1.4 Représentation visuelle des données
 Elle doit permettre à l’utilisateur de visualiser un jeu de données en fonction de critères à
préciser (date, type d’événement, lieu, …)
1.1.5 Paramétrage de la collecte / administration
La partie administration englobe notamment :
 La définition des sources, outils…
 Les règles d’extraction, de nettoyage,…
 La politique de mise à jour, rafraîchissement
 Le cycle de vie de la donnée, fraîcheur de la donnée
1.2
Analyse fonctionnelle
L’outil à développer peut être vu au travers des étapes décrites dans le schéma ci-dessous :
Données HTML
(source HTTP)
Wrapper
Grammaire
(fichier .nf)
(programme
Java)
Ecrite après
analyse du
code source :
Analyse de la
sémantique
Résultats
(Fichiers de sortie)
.txt
Nettoyage des données
- Détection des doublons
- Annulation des données
obsolètes
<Calendrier>
<Evenements Date= ‘’01.01.02’’>
<Evenement
Type=’’Fest-noz’’ Lieu=’’Brélès’’
Acteurs=’’Kael’’>
<\Evenement>
<\Evenements>
<\Calendrier>
Parseur
Stockage des
données
(programme
Java)
Requête
Formulaire de reche rche
.xml
Résultat de l a requête
Affichage des réponses
Portail Trad.org
Figure 1 : schéma des principales étapes du projet
6
n fichiers XML (format unifié)
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Le travail réalisé jusqu’à présent couvre la phase d’extraction des données, de l’analyse des sources
d’information au parsing. Les solutions techniques choisies font l’objet de la seconde partie. Pour
alléger l’exposé, les programmes et autres données techniques sont placés en annexes.
7
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Partie 2
2 Solutions techniques proposées
L’information à extraire est contenue dans des pages écrites en HTML (HyperTextMarkup Language).
Par essence, ce langage n’est pas destiné au stockage des données, mais à leur affichage et à la
liaison entre les différentes parcelles d’information. De ce fait, mais aussi en raison du manque de
rigueur dans l’écriture du code, les items dans les pages HTML sont difficiles à capturer par des
parseurs grammaticaux ordinaires.
Pour convertir un texte mal structuré en une collection d’objets de base de donnée, les étapes clés
sont l’identification des informations contenues dans le texte, l’extraction des données et la
construction d’une représentation qui pourra être manipulée par un langage de requête.
Ce procédé, appelé « wrapping » se fait grâce à un module logiciel, l’adaptateur (ou wrapper).
Plusieurs projets portent sur la génération automatique de wrappers. Les principaux (ARANEUS [1],
XWRAP [2], TSIMMIS [3], W4F [4]) permettent de concevoir un outil paramétrable selon le modèle et
les sources de données.
L’outil utilisé dans le cadre de ce projet est Araneus.
Cet outil s’appuie sur un formalisme, appelé Minerva1, permettant de générer un wrapper à partir de
sources de données Web et semi-structurées. Sa particularité est qu’il tente de combiner les
avantages d’une approche déclarative, basée sur une grammaire, et la flexibilité d’une programmation
procédurale pour le traitement des hétérogénéités et des exceptions.
1
Minerva a été développé dans le framework d‘Araneus, un projet de recherche de l’Université de Romes
8
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Il propose un compromis entre une approche déclarative et une programmation procédurale, en
incorporant dans un parser grammatical, un mécanisme de traitement des exceptions. Cela se fait en
annotant les productions de grammaire avec une clause d’exception, contenant un morceau de code
procédural. Durant le parsing, si une des productions échoue, une exception est levée et la clause
d’exception correspondante est invoquée. Le code est alors exécuté afin de tenter de restructurer le
document source et de reprendre le parsing.
2.1
Analyse de la source, détection de l’information utile et définition d’un
format unifié
La première phase du travail repose sur l’analyse du fichier source (HTML) et l’écriture d’un fichier de
description (ou grammaire).
2.1.1
Site analysé
Parmi les sites à analyser, certains seront difficilement exploitables 2. C’est le cas des sites dont les
données textuelles ne présentent pas de logique de classement ou n’apparaissent que de manière
facultative, et pour lesquels l’extraction de l’information utile impose d’en connaître le sens.
Le site (http://www.bzh5.com/gouel/degemer.php), choisi ici pour tester l’outil, présente une structure
simple. Réalisé en PHP, il se prête facilement à l’extraction de données. Les informations sont le
résultat d’une requête et sont présentées dans un tableau de manière homogène.
Toutefois, comme il a été dit précédemment, l’outil Araneus est conçu pour traiter les exceptions et
pourra être utilisé pour extraire l’information de pages moins bien structurées.
2.1.2
Détection de l’information utile, écriture du fichier de description
Le site analysé présente des événements classés par date. Chaque date fait partie d’une liste, dont
les balises constituent un point de repère. Pour une date donnée, les événements sont présentés
dans un tableau. Chaque événement est décrit par le type d’événement (fest-noz, …), le lieu (ville en
breton, [département], ville en français), les acteurs (groupe, artiste). Un lien permet d’accéder à un
complément d’information.
2
L’analyse des sites est présentée en annexe 3
9
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Figure 2 : liste des événements, classés par date, du site http://www.bzh5.com/gouel/degemer.php
Un événement se caractérise donc par une date, un type, un lieu et des acteurs. Ces données
constituent l’information utile que l’on doit extraire du code source HTML, présenté dans
l’annexe 1 (§ 2). La grammaire3 (fichier au format .nf) est générée en exploitant les balises
caractéristiques encadrant les données à récupérer. C’est à partir de cette grammaire que le wrapper
sera ensuite construit.
La grammaire est présentée en annexe 1 (§ 3). La première partie de cette annexe (§ 1) répertorie les
principales commandes utilisées pour construire le wrapper à partir de la grammaire, puis pour
extraire les données et les recueillir dans un fichier de sortie.
3
ce rapport ne met volontairement pas l’accent sur la réalisation de la grammaire, car l’outil Araneus propose
dans sa documentation, un très bon tutorial l’expliquant et mettant notamment l’accent sur le traitement des
exceptions.
10
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
2.1.3
Récupération de l’information utile dans un fichier au format XML
Le wrapper Araneus génère en sortie un fichier au format .txt ou .xml. Le format XML présente de
multiples avantages. Contrairement à HTML, XML définit un format de données hautement structuré,
qui ne mélange pas l’information et la mise en forme du document.
La phase de conception nous oriente sur la structure logique du calendrier. La racine du document
XML est représentée par l’objet Calendrier. Cet élément peut posséder une infinité d’enfants incarnés
par les objets Evenements, caractérisé par l’attribut Date. A chaque date correspond une infinité
d’enfants Evenement, dont les attributs sont le Type, le Lieu et les Acteurs.
Calendrier
Evenements
Date
Evenement
Type
Lieu
Acteur
Evenement
Type
Lieu
Acteur
Evenements
Date
Evenement
Type
Lieu
Acteur
Figure 3 : Structure du calendrier
11
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Le fichier XML4 est généré selon la structure présentée ci-dessus :
Figure 4 : l’information utile est recueillie dans un fichier XML
La séparation du contenu et de la forme permet d’extraire facilement les informations du document
par un simple parsing.
2.2
Le parsing
Un parseur [5], [6] est un programme capable de récupérer des informations contenues dans un fichier
XML. Un jeu d’instruction vise à extraire les données sans avoir à s’occuper de la syntaxe du XML. Le
principe des parseurs est le suivant : on donne l’appellation de la balise, et l’on obtient en retour la valeur
comprise entre cette balise ouvrante et sa jumelle fermante.
Le parseur est utilisé par l’application pour traiter les données XML. Les APIs jouent le rôle d’interface.
Il existe 2 types de parseurs, qui utilisent des APIs distinctes :
4
A noter que le fichier XML généré comporte en première ligne le chemin du fichier source qui donne lieu à un
message d’erreur. Le caractère « & », qui n’est pas interprété, est remplacé par &amp. Ces corrections ont été
apportées manuellement. Dans la suite du projet, il faudra traiter plus élégamment ces deux cas.
12
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »

le premier type de parseur compile l’ensemble du document et construit une représentation sous
forme d’arbre d’objets (les attributs et méthodes permettent la manipulation de la structure logique
et de l’information contenue dans le document). Il utilise l’API DOM.

Le second type lit le flot de données XML en entrée, reconnaît et interprète les balises. Ce
modèle, appelé « traitement dirigé par les événements », utilise l’API SAX.
La figure ci-dessous met en évidence le rôle du parseur et de l’API :
Figure 5 : rôle d’un parseur XML & API DOM
2.2.1
Les APIs des parseurs
Les APIs des parsers [7] sont des composants logiciels permettant d’accéder facilement aux données
contenues dans un document XML. C’est le but de SAX (Simple API for XML) et de DOM (Document
Object Model). JAXP est une API qui rend le code d’une application XML indépendant du parser utilisé.
Le principe, les avantages et inconvénients des principales APIs sont présentés dans le tableau ciaprès.
13
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
SAX (Simple API
for XML)
DOM (Document
Object Model)
JAXP (Java API
for XML Parsing)
2.2.2
Principe
Avantages et inconvénients
On accorde au parser SAX des objets
dont les méthodes (implantant des
interfaces précises) sont appelées par le
parser lorsque certains événements se
produisent au cours du parsing du fichier
XML.
SAX est très rapide, mais ne permet
pas de transformer l’arbre lors du
parsing (il ne fait que consommer les
données). La norme permet d’écrire
des applications indépendantes du
parser utilisé (il permet de produire du
code standard qui s’adapte, sans
recompilation.
DOM permet de représenter un
document XML sous forme d’un arbre
d’objets en mémoire. Il définit une API
pour parcourir et modifier l’arborescence.
DOM est indiqué pour des
applications modifiant l’arbre du
document (ex : éditeur graphique de
fichiers XML).
Quelques défauts : il est lent,
gourmand en mémoire ; la norme est
incomplète.
API mise au point par Sun pour le
parsing XML afin de résoudre les
problèmes de dépendance du code au
parser. Son API est une enveloppe pour
rendre le code d’une application XML
indépendant du parser utilisé. Elle
encapsule la création et le paramétrage
des parsers SAX et DOM.
Le code est totalement indépendant
du parser utilisé et fonctionne avec
tout parser conforme à l’API JAXP.
Développement du parseur en Java
Le parseur développé ici et présenté en annexe utilise l’API JAXP.
Une première partie du programme parse et charge les informations dans un document objet, qui
désigne un arbre de nœuds contenant les données et la structure de l’information.
Les classes appartenant au package javax.xml.parsers, utilisées dans le programme sont décrites cidessous :
-
DocumentBuilderFactory définit une API de construction qui permet aux applications d’obtenir un
parseur qui produit les arbres d’objet DOM à partir du document XML
-
DocumentBuilder définit l’API d’obtention de l’instance de document DOM à partir du document
XML
-
FactoryConfigurationError informe des erreurs de configuration
-
ParserConfigurationException informe des problèmes sérieux de configuration
14
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
La structure DOM est ensuite parcourue, nœud par nœud grâce à 2 méthodes essentielles :
getNodeName( ) et getNodeValue( ).
Le traitement du nœud racine, des nœuds enfants et attributs (nœuds sans enfant) permet
successivement de parser l’ensemble du fichier XML. Les classes java qui constituent le parseur sont
présentées dans l’annexe 2.
15
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
3 Conclusion
Ce projet couvre plusieurs facettes allant de l’extraction des données à la visualisation des
informations dans le portail. Le travail présenté dans ce rapport englobe l’analyse du besoin et offre
des solutions pour l’extraction des données, constituant la première phase du projet.
Les autres étapes n’ont pas été traitées. Une réflexion menée sur le stockage des données montre
que deux solutions simples peuvent être envisagées. Comme nous le savons, XML constitue une
bonne méthode de structuration des données. La nature structurelle des documents XML se révèle
propice à l’emploi d’un langage de requêtes pour accéder à des éléments de l’arbre. Xpath, le
pendant de SQL pour XML, permet d’opérer des recherches très poussées sur les documents XML.
Cette méthode peut être combinée à une base de données relationnelle, telle que MySQL, qui offre
elle aussi des avantages, tels que la facilité de gestion, la fiabilité des fonctionnalités et de la sécurité.
16
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
4 Bibliographie
[1]
ARANEUS : http://www.difa.unibas.it/araneus
[2]
XWRAP : http://www.cc.gatech.edu/projects/disl/XWRAP/xwrap.html
[3]
TSIMMIS : http://www-db.stanford.edu/tsimmis/
[4]
W4F : http://db.cis.upenn.edu/W4F/
[5]
Michel Casabianca « Développement XML en Java sous Linux »
http://www.sdv.fr/pages/casa/html/java-xml.html
[6]
O. Aboukhaled, C. Vanoirbeek « Gestion de documents XML »
[7]
API JAXP (Java API for XML Parsing)
http://java.sun.com/xml/jaxp/
17
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
ANNEXE 1
1- Araneus : guide des commandes utilisées
a- Utilisation de mwg
mwg est une classe Java, utilisée pour générer un wrappeur (une classe java) à partir d’une
grammaire (fichier .NF). Elle utilise un fichier de propriétés (minerva/minerva.properties)
qui, par une ligne de commande, compile le source Java généré
(minerva.mwg.compiler=javac).
Il s’utilise de la manière suivante :
java mwg INPUTFILE OUTPUTWRAPPER
Cette commande génère à partir du code .NF (INPUTFILE) le wrapper correspondant dans un
fichier (OUTPUTWRAPPER).
Un exemple : java mwg trads\NFFiles\test.nf test.java
Cette commande produit, dans le répertoire courant, un wrapper appelé « test.java» à partir
des spécifications se trouvant dans le fichier : "trads\NFFiles\test.nf".
b- Extraction des données
On utilise ensuite la commande suivante pour extraire les données en utilisant le wrapper :
Usage: java <wrapper> NT SOURCE ...
Cette ligne « wrappe » le document source (fichier stocké localement ou URL). NT est le « root »
utilisé pour débuter le parsing. Le wrapper se connecte à la source, extrait les données et
retourne le résultat.
Un exemple :
java test S trads\html\capture1.htm
c- Format de sortie
Les données extraites peuvent être présentées dans un fichier au format XML, en utilisant
out.print().
Pour générer le fichier XML :
java test S trads\html\capture1.htm > test.xml
18
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
2- Source HTML de la page analysée (http://www.bzh5.com/gouel/degemer.php)
<table width="95%" border="1" cellspacing="0" cellpadding="5" align="center" class=m12
bordercolor="#006600">
<tr valign="top">
<td bgcolor="#FFFFFF">
<b> 224 réponses trouvées</b> en Bretagne.</font><div align=center>    <span
class=m13>Page </span><span class=m13><b>1</b> </span><a href="#"
onClick="document.ff.lech.value=10;document.ff.kum.value='100';document.ff.submit()"><span
class=m13>2</span></a> <a href="#"
onClick="document.ff.lech.value=20;document.ff.kum.value='100';document.ff.submit()"><span
class=m13>3</span></a>
[etc…]
onClick="document.ff.lech.value=10;document.ff.kum.value='100';document.ff.submit()"><img src="davdehou.gif"
border=0 align=absbottom></a>  </div>
<font color=#663333 class=m12><b>• Dimanche 10 février 2002</b> <a href="diskkart.php?yezh=1&sizh=10022002&petra=1">Carte de ce jour</a></font>
<table border=1 Cellpadding=1 Cellspacing=0 width=90% class=m12 align=center>
<tr bgcolor="#FFFFCC">
<td width=4% nowrap><div align=center><b>Fest-deiz</b></div></td>
<td width=30%><div align=center><b></b><br>Ar C'hembod [22]<br>
<span class=m10>(Le Cambout)</span></div></td>
<td><table border=0 Cellpadding=4 Cellspacing=0 class=m12><tr><td> avec : </td>
<td>Les accordéonistes diato du CADB<br></td></tr></table></td>
<td width=16% nowrap><div align="center"><a href='diskfest.php?n=603&yezh=1'><img src="klkart.gif"
width="28" height="21"border="0"><br>Détails et carte</a></td>
</tr>
<tr bgcolor="#FFFFFF">
<td width=4% nowrap><div align=center><b>Fest-deiz</b></div></td>
<td width=30%><div align=center><b></b><br>St-Karadeg [22]<br>
<span class=m10>(St-Caradec)</span></div></td>
<td><table border=0 Cellpadding=4 Cellspacing=0 class=m12><tr><td> avec : </td>
<td>Kasadenn<br>Les Chantous d'Loudia<br>Gaïa<br></td></tr></table></td>
<td width=16% nowrap><div align="center"><a href='diskfest.php?n=679&yezh=1'><img src="klkart.gif"
width="28" height="21"border="0"><br>Détails et carte</a></td>
</tr>
[etc…]
</table>
<br>
<font color=#663333 class=m12><b>• Samedi 16 février 2002</b> - <a
href="diskkart.php?yezh=1&sizh=16022002&petra=7">Carte de ce jour</a></font>
< table border=1 Cellpadding=1 Cellspacing=0 width=90% class=m12 align=center>
<tr bgcolor="#FFFFCC">
<td width=4% nowrap><div align=center><b>Fest-noz</b></div></td>
<td width=30%><div align=center><b></b><br>Pleneventer [22]<br>
<span class=m10>(Plaintel)</span></div></td>
<td><table border=0 Cellpadding=4 Cellspacing=0 class=m12><tr><td> avec : </td>
<td>Bizibul<br>L'Echo du Gouet<br>Kael<br></td></tr></table></td>
<td width=16% nowrap><div align="center"><a href='diskfest.php?n=524&yezh=1'><img src="klkart.gif"
width="28" height="21"border="0"><br>Détails et carte</a></td>
</tr>
</table>
<p> </p></td>
<td width="5%"> </td>
</tr>
</table>
</td>
19
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
<td valign=top width=3% align=right> <img src="/skd/kornnd.gif" width=20 height=20></td>
</tr>
<tr>
<td valign=top width=2% height=14 bgcolor="#FFFFCC"><img src="/skd/traonkl.gif" width=20 height=20></td>
<td width=18% class=bih height=14 valign="top" bgcolor="#FFFFCC"> </td>
<td width="77%">
<div align=right><i>www.fest-noz.net est un service gratuit proposé par <a
href=http://www.bzh5.com>www.Bzh5.com</a></i></div>
</td>
<td valign=top width=3% align=right height=14><img src="/skd/korntd.gif" width=20 height=20></td>
</tr>
</table>
<p> </p>
</body></HTML>
20
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
3- Grammaire générée (fichier au format .nf) après analyse du code HTML
//suppression des codes genants sous Windows
options {
REMOVE_BLANKS
TABULATOR("[","\t","]\n")
}
PAGE test
//decomposition des traitements pour identifier:
//dans un premier temps la date de creation du document
//dans un second temps la date des evenements
$S: { out.print("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"); }
$TraitementDate { out.print("<Calendrier>"); } $TousResultats {
out.print("</Calendrier>\n"); };
//Syntaxe : Mercredi 20 février 2002
$TraitementDate: *<div[ ]align=right><font[ ]class=m11[
]color=#FFFFFF><b>$DateComplete</b>[ ]</font></div>?;
$TousResultats: ( $TraitementPeriode $TableResultats )+ ;
//Syntaxe : <font color=#663333 class=m12><b>• Samedi 2 février
2002</b> - <a href="diskkart.php?yezh=1&sizh=02022002&petra=7">Carte de ce
jour</a></font>
$TraitementPeriode: *<font[ ]color=#663333[
]class=m12><b>&#149[;]&nbsp[;]$DateComplete { out.print("<Evenements
Date=\"" + $DateComplete + "\">\n"); } </b>[ ]-[ ]<a[
]href="diskkart.php?yezh=1&sizh=02022002&petra=7">Carte[ ]de[ ]ce[
]jour</a></font>? ;
//{ out.print($Journee+" "+$DateJour+" "+$Mois+" "+$Annee);}
//{ out.print("<Evenements Date=\""); } $DateComplete { out.print("\">\n");
}
//Syntaxe : <table ...>
//
<tr ...>
//
<td ...> TYPE EVENEMENT ... </td>
//
<td ...>
//
<td>
//
<table ...>
//
<tr>
//
<td>
//
<td> LES ACTEURS ... </td>
//
</tr>
//
</table>
//
<td>
//
<td ...> non utilise
//
</td>
//
</tr>
// ... (on recommence autant de fois)
//
</table>
//$TableResultats: $EnteteTable ($CorpsTable)+ $PiedTable ;
$TableResultats: $EnteteTable ($CorpsTable)+ $PiedTable {
out.print("</Evenements>\n"); };
21
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
$EnteteTable: *<table[ ]border=1[ ]Cellpadding=1[ ]Cellspacing=0[
]width=90%[ ]class=m12[ ]align=center>;
$CorpsTable:
<tr[ ]bgcolor="(#FFFFCC|#FFFFFF)">
<td[ ]width=4%[ ]nowrap><div[ ]align=center><b> $TypeEvt {
out.print("<Evenement Type=\"" + $TypeEvt + "\""); } </b></div></td>
<td[ ]width=30%><div[ ]align=center><b></b><br> $LieuBZH
[[]$Departement[]] <br><span[ ]class=m10>[(]$LieuFR { out.print(" Lieu=\""
+ $LieuFR + "\""); } [)]</span></div></td>
<td>
<table[ ]border=0[ ]Cellpadding=4[ ]Cellspacing=0[
]class=m12>
<tr>
<td>avec[ ][:]&nbsp[;]</td>
<td> $Artist{ out.print(" Acteurs=\"" + $Artist); }
<br>( $Artiste <br> { out.print(", " + $Artiste); } )* {
out.print("\">\n"); }
</td>
</tr>
</table>
</td>
<td[ ]width=16%[ ]nowrap><div[
]align="center">$Divers</a></td>
</tr>
{ out.print("</Evenement>\n"); }
;
$PiedTable: *</table> ? ;
//factorisation du traitement des dates
$DateComplete: $Journee[ ]$DateJour[ ]$Mois[ ]$Annee;
//decomposation des dates
$Annee: \d\d\d\d;
$DateJour: (\d)+;
$Mois: [A-Za-zé]+;
$Journee: [A-Za-z]+;
//Le type d evenement a traiter
$TypeEvt: [A-Za-z0-9-éèà]+;
//Le lieu
$LieuFR: [A-Za-zéèà '"-]+;
$LieuBZH: [A-Za-z0-9éèêà '"-]+;
$Departement: (\d)+;
//Liste des artistes
$Artist: [A-Za-z0-9-/& éèàêï'"]+ ;
$Artiste: [A-Za-z0-9-/& éèàêï'"]+ ;
//... rien a faire
$Divers: *(?</a></td>)?;
//traitement des exceptions
END
22
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
ANNEXE 2
Code source des classes du parseur
ParsCalendrier.java
package calendrier;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.io.*;
import org.w3c.dom.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.Date;
/**
* Cette classe realise le parsing XML
*/
public class ParsCalendrier {
private static Document document;
/* chemin du fichier XML a parser */
public static String S_PATH = "xml/test.xml";
/* activation de la trace */
private static final boolean DEBUG = true;
/* constantes de recherche dans le fichier XML */
private final static String S_CALENDRIER = "Calendrier";
private final static int I_EVTS_NB = 1;
private final static String S_EVTS = "Evenements";
private final static String S_EVTS_DATE = "Date";
private final static int I_EVT_NB = 3;
private final static String S_EVT = "Evenement";
private final static String S_EVT_TYPE = "Type";
private final static String S_EVT_LIEU = "Lieu";
private final static String S_EVT_ACTEURS = "Acteurs";
23
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
//Création d'un vecteur pour stocker les différentes dates du calendrier
public static Vector listeEvenements=new Vector();
public static void main(String [] args) {
System.out.println("Demarrage du processus. SVP, attendez.......");
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse( new File(S_PATH) );
} catch (SAXException sxe) {
// Error generated during parsing)
Exception x = sxe;
if (sxe.getException() != null)
x = sxe.getException();
x.printStackTrace();
} catch (ParserConfigurationException pce) {
// Parser with specified options can't be built
pce.printStackTrace();
} catch (IOException ioe) {
// I/O error
ioe.printStackTrace();
}
// on peut travailler maintenant sur le document mis en memoire
// on met en memoire tt ce ont on a besoin
traiterDocument();
// on presente les resultats a l ecran
//
presenterResultats();
System.out.println("le processus est termine.");
} // main
/**
* cette methode est la cle de voute de l'application
* elle recupere une liste de tous les noeuds 'Evenements',
* puis appelle pour chacun de ces noeuds des methodes pour
* recuperer des informations sur les parametres et sur les
* fonctions
*/
public void addListeEvenements(C_Evenements _listeEvenements){
listeEvenements.addElement(_listeEvenements);
}
public void removeListeEvenements(C_Evenements _listeEvenements){
listeEvenements.removeElement(_listeEvenements);
24
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
}
public void setListeEvenements(Vector _listeEvenements){
listeEvenements=_listeEvenements;
}
public Vector getListeEvenements(){ return listeEvenements; }
public static void traiterDocument() {
String nomNode=document.getNodeName();
System.out.println("Type de NODE :"+nomNode);
System.out.println("Racine :"+document.getFirstChild().getNodeName());
//****************** niveau 0 : racine **************************
// recherche le noeud principal et traite ses attributs
NodeList paramNodeList = document.getElementsByTagName(S_CALENDRIER);
traiterCalendrier(paramNodeList.item(0));
//****************** niveau 1 ***********************************
// recherche le noeud definissant les événements et on traite ses attributs
paramNodeList = document.getElementsByTagName(S_EVTS);
for(int i=0; i< paramNodeList.getLength();i++) {
Node paramNode = paramNodeList.item(i);
// pour chacun de ces noeuds, on fait appel à la méthode traiterEvenements
if(DEBUG) System.out.println("Evenements : "+paramNode);
traiterEvenements(paramNode);
}
}
/**
* noeud principal
*/
private static void traiterCalendrier(Node Evenements) {
}
/**
* methode qui recupere les attributs du noeud de 1er niveau : evenements
*
* principe :
* - on recupere les attributs du noeud
*/
private static void traiterEvenements(Node Evenement) {
// on recupere les attributs du noeud
NamedNodeMap attributes = Evenement.getAttributes();
Node attrEvenements = attributes.getNamedItem(S_EVTS_DATE);
if(DEBUG) System.out.println(">>>>>>>>>>>> Date de l'événement :
["+attrEvenements.getNodeValue()+"] <<<<<<<<<<<<");
25
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
// creation de l'événement et initialisation de la date
C_Evenements unEvenement = new C_Evenements();
unEvenement.set_dateEvenement(attrEvenements.getNodeValue());
// ajout dans la liste
listeEvenements.addElement(unEvenement);
// traitement du noeud defini dans Evenements
// recherche le noeud et traite ses attributs
NodeList noeudsEvenement = ((Element)Evenement).getElementsByTagName(S_EVT);
for(int i=0; i< noeudsEvenement.getLength();i++) {
Node paramNode = noeudsEvenement.item(i);
// on fait appel à la méthode traiterEvenement
traiterEvenement(paramNode, unEvenement);
}
}
/** Methode qui recupere le nom d'un parametre */
private static void traiterEvenement(Node evenement, C_Evenements __evenements) {
/* sous une implementation DOM, chaque noeud a un fils "TEXT NODE",
c'est ce noeud qui contient la valeur contenue entre les tags
*/
// on recupere les attributs du noeud
NamedNodeMap attributes = evenement.getAttributes();
System.out.println("Nombre d'attributs lus:"+attributes.getLength());
if(attributes.getLength() != I_EVT_NB) {
System.out.println("Le document XML n'est pas bien forme");
System.exit(0);
}
// on recupere les noeuds correspondant aux attributs
Node attrType = attributes.getNamedItem(S_EVT_TYPE);
Node attrLieu = attributes.getNamedItem(S_EVT_LIEU);
Node attrActeurs = attributes.getNamedItem(S_EVT_ACTEURS);
if(DEBUG) System.out.println("Evenement :");
if(DEBUG) System.out.println("- Type : "+attrType.getNodeValue());
if(DEBUG) System.out.println("- Lieu : "+attrLieu.getNodeValue());
if(DEBUG) System.out.println("- Acteurs : "+attrActeurs.getNodeValue());
// creation du parametre et ajout dans la liste des parametres de la station courante
C_Evenement unEvenement = new C_Evenement();
unEvenement.set_typeEvenement((String)attrType.getNodeValue());
unEvenement.set_lieuEvenement((String)attrLieu.getNodeValue());
unEvenement.set_acteursEvenement((String)attrActeurs.getNodeValue());
__evenements.addListeEvts(unEvenement);
}
26
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
/**
* cette méthode lit le fichier de donnees dont le nom
* est passe en parametre, stocke chaque donnee rencontree
* au format 'Double' dans une liste qu'elle retourne
*/
private static ArrayList lireFichier(String filename) {
ArrayList resultat = new ArrayList();
if(DEBUG) System.out.println("Lecture du fichier de donnees");
try {
// on cree n flux pour lire le fichier
BufferedReader br = new BufferedReader(new FileReader(filename));
String chaine = br.readLine();
while(chaine != null) {
if(DEBUG) System.out.println("valeur : "+chaine);
chaine.trim();
// les valeurs du fichier sont stockees dans la hashmap sous
// forme d'objet Double
if(!chaine.equals("")) resultat.add(Double.valueOf(chaine));
chaine = br.readLine();
}
}
catch(FileNotFoundException fnfe) {
System.out.println("Le fichier de donnees n'a pas ete trouve ; le chemin est incorrect");
System.out.println(fnfe + " " +fnfe.getMessage());
}
catch(IOException ioe) {
System.out.println("Probleme lors de la recuperation des fichiers de donnees");
System.out.println(ioe + " " + ioe.getMessage());
System.exit(0);
}
return resultat;
}
}
C_Evenements.java
package calendrier;
/*
* generated with velocity template engine
*
*/
import java.util.*;
import java.lang.String;
public class C_Evenements {
//attributes
private String _dateEvenement;
public void set_dateEvenement(String __dateEvenement){_dateEvenement=__dateEvenement;}
public String get_dateEvenement(){return _dateEvenement;}
//associations
27
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
public Vector listeEvts=new Vector();
public void addListeEvts(C_Evenement _listeEvts){
listeEvts.addElement(_listeEvts);
}
public void removeListeEvts(C_Evenement _listeEvts){
listeEvts.removeElement(_listeEvts);
}
public void setListeEvts(Vector _listeEvts){
listeEvts=_listeEvts;
}
public Vector getListeEvts(){ return listeEvts; }
}
C_Evenement.java
package calendrier;
/*
* generated with velocity template engine
*
*/
import java.util.*;
import java.lang.String;
//import java.lang.Float;
public class C_Evenement {
//attributes
private String _typeEvenement;
private String _lieuEvenement;
private String _acteursEvenement;
public void set_typeEvenement(String __typeEvenement){_typeEvenement=__typeEvenement;}
public String get_typeEvenement(){return _typeEvenement;}
public void set_lieuEvenement(String __lieuEvenement){_lieuEvenement=__lieuEvenement;}
public String get_lieuEvenement(){return _lieuEvenement;}
public void set_acteursEvenement(String
__acteursEvenement){_acteursEvenement=__acteursEvenement;}
public String get_acteursEvenement(){return _acteursEvenement;}
//associations
}
28
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
ANNEXE 3
1- Analyse des sites
http://trad75.free.fr/
Données textuelles présentées sur une ligne ; il existe une
logique dans le classement, avec certaines informations
facultatives. Pour pouvoir distinguer les différents types
d’informations caractérisant un événement, il est nécessaire
d’en connaître le sens, car rien dans la structure du document
permet de les identifier.
Difficilement exploitable
Informations :
-
date (les événements sont classés selon ce critère)
type d’événement (bal, concert, stage)
adresse (ville – département - arrondissement, rue)
heure de déroulement
nom du groupe, des intervenants, et toute autre information concernant l’événement
prix (en euros ou entrée libre)
n° de téléphone (facultatif)
adresse e-mail, url (facultatif)
Analyse :




Il existe une logique dans le classement
Les informations fournies concernant un événement sont nombreuses
Le calendrier est fourni (10 pages)
Le nom des acteurs ne peut pas être distingué des autres informations fournies sans en connaître
le sens
http://www.bzh5.com/gouel/degemer.php
Site réalisé avec PHP. Page structurée. Les
informations sont le résultat d’une requête. Elles
sont présentées dans un tableau, de manière
homogène.
Exploitable
Recherche dynamique par date, groupe/artiste, lieu
Les résultats sont donnés par jour. Chaque date fait partie d’une liste, dont les balises doivent
constituer un point de repère.
Les informations, pour une date donnée, sont présentées dans un tableau. Chaque ligne décrit un
événement. Par ligne, on retrouve 3 informations + 1 colonne permettant d’accéder à un complément
d’information.
Informations
- date
- type d’événement (fest-noz, …)
- lieu (ville en breton, [département], ville en français)
- Acteurs (groupe, artiste)
- Détail
29
16/04/17
Projet d’ingénierie « Méta-calendrier automatique pour portail www »
Page statique réalisée en HTML. Il n’y a pas
d’homogénéité dans la présentation des champs
(cela signifie qu’il sera difficile d’extraire
l’information minimale utile, étape nécessaire
pour détecter les doublons par exemple). La
structure en tableau permet cependant de
distinguer clairement la nature de l’information.
http://www.normandiefolk.com/
normandiefolk/agenda2.htm
Exploitable
Page statique ; les événements sont classés par mois
Les résultats sont donnés par jour. Chaque date fait partie d’une liste, dont les balises doivent
constituer un point de repère.
Les informations, pour une date donnée, sont présentées dans un tableau. Chaque ligne décrit un
événement. Par ligne, on retrouve 4 informations et 1 colonne permettant d’accéder à un complément
d’information.
Informations
- date (pas d’homogénéité dans la présentation de ce champ)
- descriptif de l’événement (idem)
- lieu
- contact
- tarif
Analyse :
 Les champs sont remplis individuellement. Il n’y a pas d’homogénéité dans la présentation.
30
Téléchargement