html.parser
— Analizador simple de HTML y XHTML¶
Código fuente: Lib/html/parser.py
Este módulo define una clase HTMLParser
que sirve como base para analizar archivos de texto formateados en HTML (HyperText Mark-up Language) y XHTML.
-
class
html.parser.
HTMLParser
(*, convert_charrefs=True)¶ Cree una instancia de analizador capaz de analizar marcado no válido.
Si convert_charrefs es
True
(el valor predeterminado), todas las referencias de caracteres (excepto las de los elementosscript
/style
) se convierten automáticamente en los caracteres Unicode correspondientes.Una instancia de
HTMLParser
se alimenta de datos HTML y llama a métodos de manejo cuando se encuentran etiquetas de inicio, etiquetas finales, texto, comentarios y otros elementos de marcado. El usuario debe subclasificarHTMLParser
y anular sus métodos para implementar el comportamiento deseado.Este analizador no verifica que las etiquetas finales coincidan con las etiquetas iniciales ni llame al manejador de etiquetas finales para los elementos que se cierran implícitamente al cerrar un elemento externo.
Distinto en la versión 3.4: argumento de palabra clave convert_charrefs agregado.
Distinto en la versión 3.5: El valor predeterminado para el argumento convert_charrefs ahora es
True
.
Aplicación ejemplo de un analizador sintáctico (parser) de HTML¶
Como ejemplo básico, a continuación hay un analizador HTML simple que usa la clase HTMLParser
para imprimir etiquetas de inicio, etiquetas finales y datos a medida que se encuentran:
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 salida será entonces:
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étodos HTMLParser
¶
instancias de HTMLParser
tienen los siguientes métodos:
-
HTMLParser.
feed
(data)¶ Alimente un poco de texto al analizador. Se procesa en la medida en que consta de elementos completos; los datos incompletos se almacenan en el búfer hasta que se introducen más datos o se llama a
close()
. data debe serstr
.
-
HTMLParser.
close
()¶ Fuerce el procesamiento de todos los datos almacenados como si fueran seguidos por una marca de fin de archivo. Este método puede ser redefinido por una clase derivada para definir un procesamiento adicional al final de la entrada, pero la versión redefinida siempre debe llamar a
HTMLParser
método de clase baseclose()
.
-
HTMLParser.
reset
()¶ Restablecer la instancia. Pierde todos los datos no procesados. Esto se llama implícitamente en el momento de la instanciación.
-
HTMLParser.
getpos
()¶ Retorna el número de línea actual y el desplazamiento.
-
HTMLParser.
get_starttag_text
()¶ Retorna el texto de la etiqueta de inicio abierta más recientemente. Normalmente, esto no debería ser necesario para el procesamiento estructurado, pero puede ser útil para tratar con HTML «como implementado» o para volver a generar entradas con cambios mínimos (se puede preservar el espacio en blanco entre los atributos, etc.).
Los siguientes métodos se invocan cuando se encuentran datos o elementos de marcado y deben anularse en una subclase. Las implementaciones de la clase base no hacen nada (excepto handle_startendtag()
):
-
HTMLParser.
handle_starttag
(tag, attrs)¶ Este método se llama para manejar el inicio de una etiqueta (por ejemplo,
<div id="main">
).El argumento tag es el nombre de la etiqueta convertida a minúsculas. El argumento attrs es una lista de pares
(nombre, valor)
que contienen los atributos encontrados dentro de los corchetes<>
de la etiqueta. El name se traducirá a minúsculas, se eliminarán las comillas en el value y se reemplazarán las referencias de caracteres y entidades.Por ejemplo, para la etiqueta
<A HREF="https://www.cwi.nl/">
, este método se llamaría comohandle_starttag('a', [('href', 'https : //www.cwi.nl/ ')])
.Todas las referencias de entidad de
html.entities
se reemplazan en los valores de los atributos.
-
HTMLParser.
handle_endtag
(tag)¶ Este método se llama para manejar la etiqueta final de un elemento (por ejemplo,
</div>
)El argumento tag es el nombre de la etiqueta convertida a minúsculas.
-
HTMLParser.
handle_startendtag
(tag, attrs)¶ Similar a
handle_starttag()
, pero llamado cuando el analizador encuentra una etiqueta vacía de estilo XHTML (<img .../>
). Este método puede ser anulado por subclases que requieren esta información léxica particular; la implementación predeterminada simplemente llamahandle_starttag()
yhandle_endtag()
.
-
HTMLParser.
handle_data
(data)¶ Este método se llama para procesar datos arbitrarios (por ejemplo, nodos de texto y el contenido de
<script>...</script>
y<style>...</style>
).
-
HTMLParser.
handle_entityref
(name)¶ Este método se llama para procesar una referencia de caracteres con nombre del formulario
&name;
(por ejemplo,>
), donde name es una referencia de entidad general (por ejemplo,'gt'
). Este método nunca se llama si convert_charrefs esTrue
.
-
HTMLParser.
handle_charref
(name)¶ Este método se llama para procesar referencias de caracteres numéricos decimales y hexadecimales de la forma
&#NNN;
y&#xNNN;
. Por ejemplo, el equivalente decimal para>
es>
, mientras que el hexadecimal es>
; en este caso, el método recibirá'62'
o'x3E'
. Este método nunca se llama si convert_charrefs esTrue
.
-
HTMLParser.
handle_comment
(data)¶ Este método se llama cuando se encuentra un comentario (por ejemplo,
<!--comment-->
).Por ejemplo, el comentario
<! - comment ->
hará que se llame a este método con el argumento'comment'
.El contenido de los comentarios condicionales de Internet Explorer (condcoms) también se enviará a este método, por lo tanto, para
<!--[if IE 9]>IE9-specific content<![endif]-->
, este método recibirá'[if IE 9]>IE9-specific content<![endif]'
.
-
HTMLParser.
handle_decl
(decl)¶ Este método se llama para manejar una declaración de tipo de documento HTML (por ejemplo,
<!DOCTYPE html>
).El parámetro decl será todo el contenido de la declaración dentro del
<!...>
markup (por ejemplo,'DOCTYPE html'
).
-
HTMLParser.
handle_pi
(data)¶ Método llamado cuando se encuentra una instrucción de procesamiento. El parámetro data contendrá toda la instrucción de procesamiento. Por ejemplo, para la instrucción de procesamiento
<?proc color='red'>
, este método se llamaría comohandle_pi("proc color='red'")
. Está destinado a ser anulado por una clase derivada; La implementación de la clase base no hace nada.Nota
La clase
HTMLParser
utiliza las reglas sintácticas SGML para procesar instrucciones. Una instrucción de procesamiento XHTML que use el'?'
final hará que se incluya el'?'
en data.
-
HTMLParser.
unknown_decl
(data)¶ Se llama a este método cuando el analizador lee una declaración no reconocida.
El parámetro data será el contenido completo de la declaración dentro del marcado
<! [...]>
. A veces es útil ser reemplazado por una clase derivada. La implementación de la clase base no hace nada.
Ejemplos¶
La siguiente clase implementa un analizador que se utilizará para ilustrar más ejemplos:
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()
Analizando un 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"
Analizando un elemento con algunos atributos y un título:
>>> 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
El contenido de los elementos script
y style
se retorna tal cual, sin más análisis
>>> 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!</strong>");</script>')
Start tag: script
attr: ('type', 'text/javascript')
Data : alert("<strong>hello!</strong>");
End tag : script
Analizando comentarios:
>>> parser.feed('<!-- a comment -->'
... '<!--[if IE 9]>IE-specific content<![endif]-->')
Comment : a comment
Comment : [if IE 9]>IE-specific content<![endif]
Analizar referencias de caracteres con nombre y numéricos y convertirlos al carácter correcto (nota: estas 3 referencias son todas equivalentes a '>'
):
>>> parser.feed('>>>')
Named ent: >
Num ent : >
Num ent : >
La alimentación de fragmentos incompletos a feed()
funciona, pero handle_data()
podría llamarse más de una vez (a menos que convert_charrefs esté configurado como True
):
>>> 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
Analizar HTML no válido (por ejemplo, atributos sin comillas) también funciona:
>>> 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