"html.parser" --- Simple HTML and XHTML parser
**********************************************

**Code source :** Lib/html/parser.py

======================================================================

Ce module définit une classe "HTMLParser" qui sert de base pour
l'analyse syntaxique de fichiers texte formatés HTML (*HyperText Mark-
up Language*, le  « langage de balisage hypertexte ») et XHTML
(*EXtensible HyperText Markup Language*, le « langage extensible de
balisage hypertexte »).

class html.parser.HTMLParser(*, convert_charrefs=True, scripting=False)

   Crée une instance d'analyseur capable de traiter tout balisage,
   même invalide.

   If *convert_charrefs* is true (the default), all character
   references (except the ones in elements like "script" and "style")
   are automatically converted to the corresponding Unicode
   characters.

   If *scripting* is false (the default), the content of the
   "noscript" element is parsed normally; if it's true, it's returned
   as is without being parsed.

   Une instance de "HTMLParser" est alimentée par des données HTML.
   Elle fait appel à des méthodes offrant un traitement spécifique
   quand est rencontré un élément de balisage : balise ouvrante ou
   fermante, textes, commentaires… Pour implémenter le comportement
   désiré, l'utilisateur crée une sous-classe de "HTMLParser" en
   surchargeant ses méthodes.

   Cet analyseur ne vérifie ni que les balises fermantes correspondent
   aux balises ouvrantes, ni n'invoque le gestionnaire de balises
   fermantes pour les éléments implicitement fermés par un élément
   extérieur.

   Modifié dans la version 3.4: L'argument *convert_charrefs* a été
   ajouté.

   Modifié dans la version 3.5: La valeur par défaut de l'argument
   *convert_charrefs* est désormais "True".

   Modifié dans la version 3.14.1: Added the *scripting* parameter.


Exemple d'application de l'analyseur HTML
=========================================

As a basic example, below is a simple HTML parser that uses the
"HTMLParser" class to print out start tags, end tags, and data as they
are encountered:

   from html.parser import HTMLParser

   class MyHTMLParser(HTMLParser):
       def handle_starttag(self, tag, attrs):
           print("Encountered a start tag:", tag)

       def handle_endtag(self, tag):
           print("Encountered an end tag :", tag)

       def handle_data(self, data):
           print("Encountered some data  :", data)

   parser = MyHTMLParser()
   parser.feed('<html><head><title>Test</title></head>'
               '<body><h1>Parse me!</h1></body></html>')

La sortie est alors :

   Encountered a start tag: html
   Encountered a start tag: head
   Encountered a start tag: title
   Encountered some data  : Test
   Encountered an end tag : title
   Encountered an end tag : head
   Encountered a start tag: body
   Encountered a start tag: h1
   Encountered some data  : Parse me!
   Encountered an end tag : h1
   Encountered an end tag : body
   Encountered an end tag : html


Méthodes de la classe "HTMLParser"
==================================

Les instances de "HTMLParser" disposent des méthodes suivantes :

HTMLParser.feed(data)

   Alimente l'analyseur avec du texte. Ce texte est traité dans la
   mesure où il constitue des éléments complets ; les données
   incomplètes sont mises dans un tampon jusqu'à ce que d'autres
   données soient fournies ou que la méthode "close()" soit appelée.
   L'argument *data* doit être de classe "str".

HTMLParser.close()

   Force le traitement de toutes les données du tampon comme si elles
   étaient suivies par un caractère *fin de fichier*. Cette méthode
   peut-être redéfinie par une classe dérivée pour ajouter des
   traitements supplémentaires à la fin de l'entrée, mais la version
   redéfinie devra impérativement appeler la méthode "close()" de la
   classe de base "HTMLParser".

HTMLParser.reset()

   Réinitialise l'instance. Toutes les données non traitées sont
   perdues. Cette méthode est appelée implicitement lors de
   l'instanciation.

HTMLParser.getpos()

   Renvoie le numéro de ligne et le numéro du caractère dans la ligne
   où le curseur est positionné.

HTMLParser.get_starttag_text()

   Return the text of the most recently opened start tag.  This should
   not normally be needed for structured processing, but may be useful
   in dealing with HTML "as deployed" or for re-generating input with
   minimal changes (whitespace between attributes can be preserved,
   etc.).

Les méthodes suivantes sont appelées lors de la rencontre de données
ou d'éléments de balisage ; elles sont destinées à être surchargées
par la sous-classe. L'implémentation de la classe de base ne fait rien
(sauf pour ce qui est de "handle_startendtag()") :

HTMLParser.handle_starttag(tag, attrs)

   Cette méthode est appelée pour traiter une balise ouvrante (p.  ex.
   "<div id="main">").

   The *tag* argument is the name of the tag converted to lower case.
   The *attrs* argument is a list of "(name, value)" pairs containing
   the attributes found inside the tag's "<>" brackets.  The *name*
   will be translated to lower case, and quotes in the *value* have
   been removed, and character and entity references have been
   replaced.  For empty attributes, *value* is "None".

   Par exemple, pour la balise "<A HREF="https://www.cwi.nl/">", cette
   méthode est appelée par "handle_starttag('a', [('href',
   'https://www.cwi.nl/')])".

   Toute référence d'entité présente dans "html.entities" est
   remplacée dans la valeur des attributs.

HTMLParser.handle_endtag(tag)

   Cette méthode est appelée pour traiter les balises fermantes (p.
   ex. "</div>").

   L'argument *tag* est le nom de la balise en minuscules.

HTMLParser.handle_startendtag(tag, attrs)

   Traitée de façon similaire à "handle_starttag()", mais appelée
   quand l'analyseur rencontre une balise vide de type *XHTML* (p.
   ex. "<img ... />"). Cette méthode peut-être surchargée par les
   sous-classes demandant cette information lexicale ;
   l'implémentation par défaut appelle simplement "handle_starttag()"
   et "handle_endtag()".

HTMLParser.handle_data(data)

   This method is called to process arbitrary data (e.g. text nodes
   and the content of elements like "script" and "style").

HTMLParser.handle_entityref(name)

   This method is called to process a named character reference of the
   form "&name;" (e.g. "&gt;"), where *name* is a general entity
   reference (e.g. "'gt'"). This method is only called if
   *convert_charrefs* is false.

HTMLParser.handle_charref(name)

   This method is called to process decimal and hexadecimal numeric
   character references of the form "&#*NNN*;" and "&#x*NNN*;".  For
   example, the decimal equivalent for "&gt;" is "&#62;", whereas the
   hexadecimal is "&#x3E;"; in this case the method will receive
   "'62'" or "'x3E'". This method is only called if *convert_charrefs*
   is false.

HTMLParser.handle_comment(data)

   Cette méthode est appelée quand un commentaire (p.  ex. "<!--
   commentaire-->") est rencontré.

   Par exemple, le commentaire "<!-- commentaire -->" provoque l'appel
   de cette méthode avec l'argument "' commentaire '".

   Le contenu des commentaires conditionnels d'Internet Explorer
   (*condcoms*) ne sont pas traités de manière particulière par
   l'analyseur.  Ils sont passés à cette méthode comme tous les autres
   commentaires. Ainsi, pour "<!--[if IE 9]>Contenu spécifique à
   IE9<![endif]-->", cette méthode sera appelée avec "'[if IE
   9]>Contenu spécifique à IE9<![endif]'".

HTMLParser.handle_decl(decl)

   Cette méthode est appelée pour traiter la déclaration *doctype* de
   HTML (p.  ex. "<!DOCTYPE html>").

   Le paramètre *decl* contient la totalité de la déclaration contenue
   dans le balisage "<!...>" (p.  ex. "'DOCTYPE html'").

HTMLParser.handle_pi(data)

   Méthode appelée quand une instruction de traitement est rencontrée.
   Le paramètre *data* contient la totalité de l'instruction de
   traitement. Par exemple, pour l'instruction de traitement "<?proc
   color='rouge'>", cette méthode est appelée par "handle_pi("proc
   color='rouge'")". Elle est destinée à être surchargée dans une
   classe dérivée ; la classe de base ne réalise aucun traitement.

   Note:

     La classe "HTMLParser" utilise les règles syntaxiques de **SGML**
     pour traiter les instructions de traitement. Une instruction de
     traitement *XHTML* utilisant une terminaison en "'?'" se traduit
     par l'inclusion de ce "'?'" dans *data*.

HTMLParser.unknown_decl(data)

   Cette méthode est appelée quand une déclaration non reconnue est
   lue par l'analyseur.

   Le paramètre *data* contient toute la déclaration enchâssée dans le
   balisage "<![...]>". Il est parfois utile de le surcharger dans une
   classe dérivée. L'implémentation de la classe de base ne réalise
   aucune opération.


Exemples
========

The following class implements a parser that will be used to
illustrate more examples:

   from html.parser import HTMLParser
   from html.entities import name2codepoint

   class MyHTMLParser(HTMLParser):
       def handle_starttag(self, tag, attrs):
           print("Start tag:", tag)
           for attr in attrs:
               print("     attr:", attr)

       def handle_endtag(self, tag):
           print("End tag  :", tag)

       def handle_data(self, data):
           print("Data     :", data)

       def handle_comment(self, data):
           print("Comment  :", data)

       def handle_entityref(self, name):
           c = chr(name2codepoint[name])
           print("Named ent:", c)

       def handle_charref(self, name):
           if name.startswith('x'):
               c = chr(int(name[1:], 16))
           else:
               c = chr(int(name))
           print("Num ent  :", c)

       def handle_decl(self, data):
           print("Decl     :", data)

   parser = MyHTMLParser()

Parsing a doctype:

   >>> parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '
   ...             '"http://www.w3.org/TR/html4/strict.dtd">')
   Decl     : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"

Parsing an element with a few attributes and a title:

   >>> parser.feed('<img src="python-logo.png" alt="The Python logo">')
   Start tag: img
        attr: ('src', 'python-logo.png')
        attr: ('alt', 'The Python logo')
   >>>
   >>> parser.feed('<h1>Python</h1>')
   Start tag: h1
   Data     : Python
   End tag  : h1

The content of elements like "script" and "style" is returned as is,
without further parsing:

   >>> parser.feed('<style type="text/css">#python { color: green }</style>')
   Start tag: style
        attr: ('type', 'text/css')
   Data     : #python { color: green }
   End tag  : style

   >>> parser.feed('<script type="text/javascript">'
   ...             'alert("<strong>hello! &#9786;</strong>");</script>')
   Start tag: script
        attr: ('type', 'text/javascript')
   Data     : alert("<strong>hello! &#9786;</strong>");
   End tag  : script

Attribute names are converted to lowercase, quotes from attribute
values removed, and "None" is returned as *value* for empty attributes
(such as "checked"):

   >>> parser.feed("<input TYPE='checkbox' checked required='' disabled=disabled>")
   Start tag: input
        attr: ('type', 'checkbox')
        attr: ('checked', None)
        attr: ('required', '')
        attr: ('disabled', 'disabled')

Parsing comments:

   >>> parser.feed('<!--a comment-->'
   ...             '<!--[if IE 9]>IE-specific content<![endif]-->')
   Comment  : a comment
   Comment  : [if IE 9]>IE-specific content<![endif]

Parsing named and numeric character references and converting them to
the correct char (note: these 3 references are all equivalent to
"'>'"):

   >>> parser = MyHTMLParser()
   >>> parser.feed('&gt;&#62;&#x3E;')
   Data     : >>>

   >>> parser = MyHTMLParser(convert_charrefs=False)
   >>> parser.feed('&gt;&#62;&#x3E;')
   Named ent: >
   Num ent  : >
   Num ent  : >

Feeding incomplete chunks to "feed()" works, but "handle_data()" might
be called more than once if *convert_charrefs* is false:

   >>> for chunk in ['<sp', 'an>buff', 'ered', ' text</s', 'pan>']:
   ...     parser.feed(chunk)
   ...
   Start tag: span
   Data     : buff
   Data     : ered
   Data     :  text
   End tag  : span

Parsing invalid HTML (e.g. unquoted attributes) also works:

   >>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')
   Start tag: p
   Start tag: a
        attr: ('class', 'link')
        attr: ('href', '#main')
   Data     : tag soup
   End tag  : p
   End tag  : a
