8.2. Presentación de sgmllib.py

El procesamiento de HTML se divide en tres pasos: obtener del HTML sus partes constitutivas, manipular las partes y reconstruirlas en un documento HTML. El primero paso lo realiza sgmllib.py, una parte de la biblioteca estándar de Python.

La clave para comprender este capítulo es darse cuenta de que HTML no es sólo texto, sino texto estructurado. La estructura se deriva de una secuencia más o menos jerárquica de etiquetas de inicio y de final. Normalmente no trabajará con HTML de esta manera; trabajará con él de forma textual en un editor de texto, o visualmente en un navegador o herramienta de autoedición. sgmllib.py presenta HTML de forma estructural.

sgmllib.py contiene una clase importante: SGMLParser. SGMLParser disgrega HTML en partes útiles, como etiquetas de inicio y fin. Tan pronto como consigue obtener algunos datos, llama a un método de sí misma basándose en lo que encontró. Para utilizar este analizador, derivará la clase SGMLParser para luego reemplazar estos métodos. A esto me refería cuando dije que presenta HTML de forma estructural: la estructura de HTML determina la secuencia de llamadas a métodos y los argumentos que se pasarán a cada uno.

SGMLParser disgrega HTML en 8 tipos de dato, e invoca métodos diferentes para cada uno de ellos:

Etiqueta de inicio
Una etiqueta HTML que inicia un bloque, como <html>, <head>, <body>, o <pre>, o una etiqueta individual como <br> o <img>. Cuando encuentra una etiqueta de inicio buscará un método llamado start_nombre_etiqueta o do_nombre_etiqueta. Por ejemplo, cuando encuentra una etiqueta <pre>, busca un método llamado start_pre o do_pre. Si encuentra el método, SGMLParser lo invoca pasando una lista de los atributos de la etiqueta; en caso contrario, llama a unknown_starttag pasándole el nombre de la etiqueta y una lista de sus atributos.
Etiqueta de fin
Una etiqueta de HTML que termina un bloque, como </html>, </head>, </body>, o </pre>. Cuando encuentra una etiqueta de fin, SGMLParser busca un método llamado end_tagname. Si lo encuentra, SGMLParser lo invoca, y si no llama a unknown_endtag pasándole el nombre de la etiqueta.
Referencia a carácter
Un carácter escapado referenciado por su equivalente decimal o hexadecimal, como &#160;. Cuando se le encuentra, SGMLParser invoca a handle_charref pasándole el texto del equivalente decimal o hexadecimal del carácter.
Referencia a entidad
Una entidad HTML, como &copy;. Cuando SGMLParser las encuentra, invoca a handle_entityref pasándole el nombre de la entidad HTML.
Comentario
Un comentario limitado por <!-- ... -->. Cuando SGMLParser lo encuentra, invoca a handle_comment pasándole el cuerpo del comenario.
Instrucción de proceso
Una instrucción de procesamiento[4] limitada por <? ... >. Cuando SGMLParser la encuentra, invoca a handle_pi pasándole el cuerpo de la instrucción.
Declaración
Una declaración de HTML, como DOCTYPE, limitada por <! ... >. Cuando SGMLParser la encuentra, invoca a handle_decl pasándole el cuerpo de la declaración.
Datos textuales
Un bloque de texto. Cualquier cosa que no caiga en ninguna de las otras 7 categorías. Cuando SGMLParser encuentra esto, invoca a handle_data pasándole el texto.
importante
Python 2.0 sufría un fallo debido al que SGMLParser no podía reconocer declaraciones (no se llamaba nunca a handle_decl), lo que quiere decir que se ignoraban los DOCTYPE sin advertirlo. Esto quedó corregido en Python 2.1.

sgmllib.py incluye una batería de pruebas para ilustrarlo. Puede ejecutar sgmllib.py pasando el nombre de un documento HTML en la línea de órdenes y esto imprimirá las etiquetas y otros elementos a medida que los reconozca. Esto lo hace derivando la clase SGMLParser y definiendo unknown_starttag, unknown_endtag, handle_data y otros métodos para que se limiten a imprimir sus argumentos.

sugerencia
En el IDE ActivePython para Windows puede especificar argumentos en la línea de órdenes desde el cuadro de diálogo “Run script”. Si incluye varios argumentos sepárelos con espacios.

Ejemplo 8.4. Prueba de ejemplo de sgmllib.py

Aquí hay un fragmento de la tabla de contenidos de la versión HTML de este libro. Por supuesto las rutas de usted pueden variar (si no ha descargado la versión HTML del libro, puede verla en http://diveintopython.org/).

c:\python23\lib> type "c:\downloads\diveintopython\html\toc\index.html"

<!DOCTYPE html
  PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
   
      <title>Dive Into Python</title>
      <link rel="stylesheet" href="diveintopython.css" type="text/css">

... se omite el resto del fichero para abreviar ...

Al pasar esto por la batería de pruebas de sgmllib.py se obtiene esta salida:

c:\python23\lib> python sgmllib.py "c:\downloads\diveintopython\html\toc\index.html"
data: '\n\n'
start tag: <html lang="en" >
data: '\n   '
start tag: <head>
data: '\n      '
start tag: <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
data: '\n   \n      '
start tag: <title>
data: 'Dive Into Python'
end tag: </title>
data: '\n      '
start tag: <link rel="stylesheet" href="diveintopython.css" type="text/css" >
data: '\n      '

... se omite el resto de la salida para abreviar ...

Aquí tiene la planificación del resto del capítulo:

Por el camino aprenderá también que existen locals, globals y cómo dar formato a cadenas usando un diccionario.

Footnotes

[4] processing instruction (PI)