INF8007 — Langages de script

Transcription

INF8007 — Langages de script
Introspection
HTML
Arbres XML
INF8007 — Langages de script
Introspection et parsage
Michel Desmarais
Génie informatique et génie logiciel
École Polytechnique de Montréal
Hiver, 2017
(30 janvier 2017)
INF8007 — Langages de script — Introspection et parsage
1/20
Introspection
HTML
Arbres XML
Introspection et parsage
1
L’introspection
2
Parseur HTML
3
Utilitaire pour arborescences XML
INF8007 — Langages de script — Introspection et parsage
2/20
Introspection
HTML
Arbres XML
Visibilité des attributs d’un objet
Les bases de l’introspection
Les attributs d’un objet sont nommés
On peut obtenir une référence à l’attribut à partir du nom
Permet un très haut niveau de dynamisme
Affichage de l’API d’un objet
Aiguillage (dispatching) basé sur des mots-clés dont certaines
librairies font usage
unittest utilise la nomenclature test <nom méthode>
INF8007 — Langages de script — Introspection et parsage
3/20
Introspection
HTML
Arbres XML
La fonction getattr
> > > li = [ ]
> > > dir ( li )
[ ' __add__ ' , ' __class__ ' , ...
' __str__ ' , ' append ' , ' count ' , ... ]
> > > getattr ( li , ' append ')
< built - in method append of list object at 0x6c2ab8 >
> > > callable ( getattr ( li , ' append ') )
True
> > > callable ( getattr ( li , ' __doc__ ') )
False
> > > f = getattr ( li , ' append ')
>>> f(2)
> > > li
[2]
INF8007 — Langages de script — Introspection et parsage
4/20
Introspection
HTML
Arbres XML
Utilisation de l’introspection
Un exemple d’utilisation de getattr() pour l’aiguillage
consiste à définir des méthodes qui suivent une nomenclature.
Par exemple :
Une classe générique est créée, foo, et comporte une méthode
de défaut pour imprimer
print default handler()
On dérive une classe de foo, la classe bar, qui comporte des
méthodes nommées selon la méthode de défaut
On suit la nomenclature : print <nom>
On définit un mécanisme pour associer un appel à la méthode
spécifique si elle existe, sinon on appelle la méthode de défaut
du parent.
Quelques détails sont donnés dans le transparents suivant et
la librairie SGML démontre une utilisation réaliste de ce
mécanisme.
INF8007 — Langages de script — Introspection et parsage
5/20
Introspection
HTML
Arbres XML
L’instrospetion à l’oeuvre
>>>
...
>>>
...
>>>
>>>
>>>
class foo ( object ) :
def p r i n t _ d e f a u l t _ h a n d l e r ( self ) : print ' foobar '
class bar ( foo ) :
def print_abc ( self ) : print ' abc '
foo_inst = foo ( )
bar_inst = bar ( )
f = getattr ( foo_inst , ' print_abc ' ,
foo_inst . p r i n t _ d e f a u l t _ h a n d l e r )
>>> f()
foobar
> > > f = getattr ( bar_inst , ' print_abc ' ,
foo_inst . p r i n t _ d e f a u l t _ h a n d l e r )
>>> f()
abc
>>>
INF8007 — Langages de script — Introspection et parsage
6/20
Introspection
HTML
Arbres XML
Introspection et parsage
1
L’introspection
2
Parseur HTML
3
Utilitaire pour arborescences XML
INF8007 — Langages de script — Introspection et parsage
7/20
Introspection
HTML
Arbres XML
Le parsage
Dans leur grand classique “Structure and interpretation of
computer languages”, Sussman et Abelson soutiennent que
tout programme de moindre envergure doit créer ses propres
abstractions linguistiques.
Fichiers de configuration
Règles (ex. règles d’affaires ; règles de composition d’images)
Traitement de la langue naturelle
INF8007 — Langages de script — Introspection et parsage
8/20
Introspection
HTML
Arbres XML
Parseur HTML de html.parser
HTML est un langage de balises issus de SGML
HTML n’a cependant pas la même exigence de rigueur qu’un
langage SGML “normal”
XML est aussi un dérivé de SGML
XML sert toutefois à la définition d’autres langages, tout
comme SGML
Le parseur html.parser définit des méthodes selon le type de
balises trouvé
INF8007 — Langages de script — Introspection et parsage
9/20
Introspection
HTML
Arbres XML
ExtracteurLiens
La gestion du début d’une balise normale est faite par
handle starttag
Exemple avec un programme qui extrait les URL :
class ExtracteurLiens ( html . parser . HTMLParser ) :
def __init__ ( self ) :
# constructeur
html . parser . HTMLParser . __init__ ( self )
self . links = [ ]
# liste des liens
def handle_starttag ( self , tag , attrs ) :
if tag = = 'a ' :
for attr in attrs :
if attr [ 0 ] = = " href " :
self . links . append ( attr [ 1 ] )
INF8007 — Langages de script — Introspection et parsage
10/20
Introspection
HTML
Arbres XML
ExtracteurLiens
La méthode handle starttag sera appelée dès qu’une balise
HTML normale <A ...> sera rencontrée.
Il s’agit alors de vérifier si le nom de la balise (dans tag) est
bien celui désiré
INF8007 — Langages de script — Introspection et parsage
11/20
Introspection
HTML
Arbres XML
Les données entre les balises
Il y a d’autres types de handler selon le type de balises
(commentaires, déclarations SGML, les caractères spéciaux, ou
autres).
On peut récupérer les données entre une balise comme : <P> Le
texte d’un paragraphe </P> avec la méthode handle data
def handle_data ( self , data ) :
print ( ' Données : ' , data )
INF8007 — Langages de script — Introspection et parsage
12/20
Introspection
HTML
Arbres XML
Utilisation
with open ( ' fichier . html ' , ' rb ') as f :
text = f . read ( )
parseur = ExtracteurLiens ( )
parseur . feed ( str ( text ) )
try :
parseur . close ( ) # Termine la lecture
except html . parser . HTMLParseError as e :
print ( html . parser . HTMLParseError )
print ( getattr (e , ' msg ') )
print ( ' Ligne : ' + str ( getattr (e , ' lineno ') ) )
links = parseur . get_links ( ) # retourne self . links
print ( ' Liens trouvés : ')
print ( links )
INF8007 — Langages de script — Introspection et parsage
13/20
Introspection
HTML
Arbres XML
Introspection et parsage
1
L’introspection
2
Parseur HTML
3
Utilitaire pour arborescences XML
INF8007 — Langages de script — Introspection et parsage
14/20
Introspection
HTML
Arbres XML
Utilitaire pour structure XML
Les structures XML sont très utilisées et des utilitaires
existent en Python pour les modèles DOM et SAX
Pour une utilisation simple, comme la gestion d’un fichier de
configuration, xml.etree.ElementTree est fort pratique :
http://docs.python.org/library/xml.etree.
elementtree.html
INF8007 — Langages de script — Introspection et parsage
15/20
Introspection
HTML
Arbres XML
Exemple
> > > from slideshow import document
> > > print document
< slideshow >
< title > Demo slideshow < / title >
< slide > < title > Slide title < / title >
< point > This is a demo < / point >
< point > Of a program for processing slides < / point >
< / slide >
< slide > < title > Another demo slide < / title >
< point > It is important < / point >
< point > To have more than < / point >
< point > one slide < / point >
< / slide >
< / slideshow >
INF8007 — Langages de script — Introspection et parsage
16/20
Introspection
HTML
Arbres XML
Exemple
Extraction
Extractions des noeuds point sous les noeuds slide :
> > > from xml . etree . ElementTree import ElementTree
> > > e = fromstring ( slideshow . document )
> > > for i in ( e . findall ( ' slide ') ) :
...
for j in i . findall ( ' point ') :
...
print ' point : % s ' % tostring ( j )
...
point : < point > This is a demo < / point >
point : < point > Of a program for processing slides < / poi
point : < point > It is important < / point >
point : < point > To have more than < / point >
point : < point > one slide < / point >
INF8007 — Langages de script — Introspection et parsage
17/20
Introspection
HTML
Arbres XML
Exemple
Texte d’un noeud
Extraction du texte des noeuds point
> > > for i in ( e . findall ( ' slide ') ) :
...
for j in i . findall ( ' point ') :
...
print ' point : % s ' % j . text
...
point : This is a demo
point : Of a program for processing slides
point : It is important
point : To have more than
point : one slide
INF8007 — Langages de script — Introspection et parsage
18/20
Introspection
HTML
Arbres XML
Manipulation de l’arbre etree
Les paquetages TreeBuilder et XMLTreeBuilder
permettent de créer des structures d’arbre
En combinant XMLTreeBuilder avec une classe comme
TreeBuilder, on peut notamment gérer des structures sur
mesure ou qui ne respectent pas la syntaxe
utile pour extraire des éléments d’un fichier HTML qui ne
ferme pas les balises !
write permet d’écrire la structure XML dans un fichier et
ElementTree.tostring() écrit dans une “string”
INF8007 — Langages de script — Introspection et parsage
19/20
Introspection
HTML
Arbres XML
Références
Voir la documentation :
http:
//docs.python.org/py3k/library/html.parser.html
http://docs.python.org/py3k/library/xml.etree.
elementtree.html
INF8007 — Langages de script — Introspection et parsage
20/20