Projet Prolog : un résumeur de site Web
L'objectif final du projet est de réaliser une application
SWI-Prolog qui, à partir d'une URL, résume automatiquement
en une unique page HTML
tout le site Web accessible de cette URL.
Par exemple, voici le résumé
de cette URL.
Les sections qui suivent vous guident pas à pas dans cette réalisation.
Pretty-print
Pour visualiser des termes SWI-Prolog, on peut s'aider de la
relation pretty_print/1
définie dans ce
fichier.
Récupérez ce fichier en local, compilez-le et testez cette relation
sur divers termes, par exemple f(X,[a,b,C],g(0,c,[6]))
.
Lancer un navigateur
- Créez et sauvegardez en local
un fichier html
bidon.html
(vous pouvez éventuellement utiliser
l'éditeur de SWI-Prolog pour cela)
avec un titre et plusieurs niveaux de balises ol
imbriqués,
du texte et des nombres.
- Cherchez comment lancer le navigateur par défaut de votre
système d'exploitation à partir de SWI-Prolog
(essayez par exemple
apropos(www)
).
A l'aide de cette relation,
visualisez la page d'acceuil de Google
ainsi que votre fichier bidon.html
.
Ecrire du code statique HTML
Lisez cette section
du manuel concernant les entrées/sorties.
Le nom du flux correspondant à la sortie standard
est user_output
.
Définissez la relation staticTable_browser/0
,
n'utilisant que la relation prédéfinie
write/2
pour créer un fichier ts.html
d'une page HTML
contenant la table des carrés de 1 à 5. Browsez.
Indications : commencez par afficher sur user_output
.
Dans un second temps, écrivez dans un fichier nommé st.html
.
Parser et générer dynamiquement du code HTML
SWI-Prolog dispose de nombreux packages,
dont la librairie sgml
, qui se charge sous SWI-Prolog
à l'aide de la directive :- use_module(library(sgml)).
- Etudiez la page HTML qui documente ce package.
- Quelle relation de ce package pouvez-vous utiliser pour lire sous SWI-Prolog de l'HTML
en local ?
Testez-la pour lire le fichier
bidon.html
.
Pretty-printez le terme lu. Analysez ce terme.
Faites de même pour le fichier st.html
.
- Quelle relation pouvez-vous utiliser pour écrire de l'HTML en local
à partir d'un terme Prolog représentant de l'HTML ?
Définissez la relation
dynamic_table(+N,-Thtml)
qui génère le terme HTML d'une page HTML intitulée Table
contenant la table des carrés de 1 à N
.
Ecrivez le code HTML dans un fichier et browsez cette page.
Indications :
lisez cette
section pour la manipulation d'atomes.
Ecrivez un code Prolog temporaire avec affichage
sur la sortie standard user_output
.
Ecrivez le code demandé.
Parcourir un arbre en profondeur d'abord
Considérez l'arbre représenté comme suit :
edges(a,[b,c,d]). edges(b,[e,f]). edges(c,[g]).
edges(d,[]). edges(e,[]). edges(f,[]). edges(g,[]).
Définissez la relation tree_thtml(+N,-T)
qui génère le terme
HTML représentant un parcours préfixe main gauche en profondeur
d'abord de l'arbre (ou du sous arbre) commençant au noeud N
.
Par exemple (la sortie a été éditée pour une meilleure lisibilité) :
?- tree_thtml(b,T),pretty_print(T).
[ b,
element(ul,[],
[ element(li,[],[e]),
element(li,[],[f])])].
T = [b, element(ul, [], [element(li, [], [e]), element(li, [], [f])])] ;
No
?-
Parcourir un graphe orienté en profondeur d'abord
Considérez le graphe :
edges2(a,[b,c,d]). edges2(b,[a,e,f]). edges2(c,[b,g]).
edges2(d,[]). edges2(e,[b]). edges2(f,[]). edges2(g,[]).
Définissez la relation graph_thtml(+N,-T)
qui génère le terme
HTML représentant un parcours préfixe main gauche en profondeur d'abord
du graphe commençant au noeud N
.
Par exemple :
?- graph_thtml(a,T),pretty_print(T).
[ a,
element(ul,[],
[ element(li,[],
[ b,
element(ul,[],
[ element(li,[],[a]),
element(li,[],
[ e,
element(ul,[],
[ element(li,[],[b])])]),
element(li,[],[f])])]),
element(li,[],
[ c,
element(ul,[],
[ element(li,[],[b]),
element(li,[],[g])])]),
element(li,[],[d])])].
T = [a, element(ul, [], [element(li, [], [b, element(ul, [], [element(li, [], [a]), element(li, [], [e, element(ul, [], [element(li, [], [b])])]), element(li, [], [f])])]), element(li, [], [c, element(ul, [], [element(li, [], [b]), element(li, [], [g])])]), element(li, [], [d])])] ;
No
Indications : attention aux cycles !
Définissez la relation not_member(+Xs,+X)
,
vraie ssi X
n'est pas élément de Xs
, en vous aidant de la relation
prédéfinie dif/2
. Utilisez la relation memberchk/2
(help(memberchk)
pour plus d'information). La relation
graph_thtml/2
peut faire appel à une relation auxiliaire où vous
maintenez, via une paire d'arguments, la liste des sommets déjà visités.
Avisez suivant l'appartenance du sommet courant à cette liste.
Télécharger une page externe
- Parmi les packages de SWI-Prolog,
parcourez la documentation de celui qui pourrait vous permettre
de ramener en local un fichier via le protocole HTTP.
- Pretty-printez le terme HTML associé à la page
http://www.w3.org/TR/html4/about.html
.
Récupérer le titre et les hrefs
- Définissez la relation
html_title(+Thtml,-Titre)
où Titre
est le titre de la structure Thtml
d'une page HTML valide. Utilisez la relation memberchk/2
.
Testez.
- Définissez la relation
html_hrefTxts(+Thtml,-HrefTxts)
où HrefTxts
est une liste des paires
lien/texte de la structure Thtml
d'une page HTML valide.
Testez.
Pour résoudre les questions suivantes, vous pourrez vous aider
de la
library(url)
.
- Définissez la relation
url_base(+URL,?Base)
où Base
est le préfixe maximum d'URL
à partir duquel on parcourt un site Web d'URL URL
.
Par exemple :
?- url_base('http://www.example.org/index.html',B).
B = 'http://www.example.org/' ;
No
?- url_base('http://www.example.org/~john',B).
No
?- url_base('http://www.example.org/~john/',B).
B = 'http://www.example.org/~john/' ;
No
Indications : auparavant lire la section concernant
la
manipulation des atomes
sous SWI-Prolog.
- Définissez la relation
is_internal_url(+URL,+Base)
vraie ssi URL
est une URL interne relativement à Base
.
Par exemple :
?- is_internal_url('test/index.html','http://www.ex.org/').
Yes
?- is_internal_url('test','http://www.ex.org/').
No
?- is_internal_url('test.html','http://www.ex.org/').
Yes
?- is_internal_url('test/','http://www.ex.org/').
Yes
?- is_internal_url('mailto://john.doe@ex.org','http://www.ex.org/').
No
?-
- Définissez la relation
url_base_absolute(+URL,+Base,-FullURL)
où FullURL
est l'URL absolue par rapport à Base
de l'URL possiblement relative URL
.
?- url_base_absolute('index.html','http://www.example.org/',F).
F = 'http://www.example.org/index.html' ;
No
?- url_base_absolute('test/index.html','http://www.example.org/',F).
F = 'http://www.example.org/test/index.html' ;
No
?- url_base_absolute('http://www.example.org/index.html','http://www.example.org/',F).
F = 'http://www.example.org/index.html' ;
No
?- url_base_absolute('~john/index.html','http://www.example.org/',F).
F = 'http://www.example.org/~john/index.html' ;
No
?- url_base_absolute('test/index.html','http://www.example.org/',F).
F = 'http://www.example.org/test/index.html' ;
No
?- url_base_absolute('test/../index.html','http://www.example.org/',F).
F = 'http://www.example.org/test/../index.html' ;
No
?-
Résumer un site Web en une unique page HTML
Définissez la relation url_summary(+URL,-Thtml)
qui résume le site d'adresse URL
en une page HTML représentée par le terme Thtml
.
Ce résumé reflète la structure du site Web,
avec les liens externes et internes du site.
- Dans un premier temps, vous supposerez que
le site Web à résumer se limite à une unique page.
- Il se peut que l'URL soit erronée.
Quels sont cas possibles ? Gérez avec
catch/3
.
- Ensuite, définissez un parcours récursif
des pages accessibles à partir de cette URL.
Documenter
Documentez et ajoutez des tests unitaires à votre programme.
Transformer en script
Transformez votre programme en un script
comme indiqué
ici.
Créer une application
- Ajoutez une fenêtre de dialogue modal pour l'entrée de l'URL.
Vous trouverez un exemple ici.
- Compilez.
Finaliser
Sous Mac OS X :
- Vous pouvez finaliser en utilisant
Platypus pour créer une application OS X.
Ces indications
peuvent être utiles.
- Vous souhaitez éviter X11 ?
Platypus peut se combiner
avec CocoaDialog.
Notez que Platypus peut également servir d'installeur,
en particulier d'une application bundlée par Platypus !
Le packaging de votre application pour d'autres plateformes m'intéresse.
Voici quelques infos.
Fred Mesnard