Parseando html con libxml2
En primer lugar tengo que comentar que no hay mucha documentación del 'binding' a python de libxml2. Básicamente las alternativas de documentarse son:
- Tirar de archivos de las listas: [1] y [2]
- Ver la ayuda: desde el interprete usar 'help(libxml2)' o desde la shell 'pydoc libxml2'.
- Ver ejemplos. Con la instalación viene alguno.
A continuación pongo un ejemplo que viene con la distribución (pushSAXhtml.py):
El poco tiempo que llevo usandolo ya me ha dado para poder reseñar que:
#!/usr/bin/python -u
import sys
import libxml2
# Memory debug specific
libxml2.debugMemory(1)
log = ""
class callback:
def startDocument(self):
global log
log = log + "startDocument:"
def endDocument(self):
global log
log = log + "endDocument:"
def startElement(self, tag, attrs):
global log
log = log + "startElement %s %s:" % (tag, attrs)
def endElement(self, tag):
global log
log = log + "endElement %s:" % (tag)
def characters(self, data):
global log
log = log + "characters: %s:" % (data)
def warning(self, msg):
global log
log = log + "warning: %s:" % (msg)
def error(self, msg):
global log
log = log + "error: %s:" % (msg)
def fatalError(self, msg):
global log
log = log + "fatalError: %s:" % (msg)
handler = callback()
ctxt = libxml2.htmlCreatePushParser(handler, "
chunk = " url='tst'>b"
ctxt.htmlParseChunk(chunk, len(chunk), 0)
chunk = "ar"
ctxt.htmlParseChunk(chunk, len(chunk), 1)
ctxt=None
.../...
El poco tiempo que llevo usandolo ya me ha dado para poder reseñar que:
- Internamente se trabaja con utf-8. Si el encoding viene especificado en el documento no hay problemas. En caso contrario supondrá uno por defecto (no realiza autodetección en este caso). El tema no es nada sencillo, ya que no sólo tenemos este problema, sino que se puede dar el caso de que el encoding no concuerde con lo que viene especificado en la declaración. O incluso que se use más de uno. Vamos una movida... Además en caso de estar parseando xhtml ignora el ?xml. Para xhtml se debería usar el parser xml, pero ¿y si el xhtml no está bien formado? Vamos que aqui hay miga...
- Desde el callback no podemos parar el parser. La parada hay que hacerla desde fuera. Lo suyo es hacerla entre el paso de un 'chunk' de datos a otro.
- Con el api de C he visto que el parser te puede notificar que ha habido un problema y que hay que parar, sin embargo esta funcionalidad no es posible en los bindings de python. Según me comenta Daniel Veillard: "The notion of fatal error where the parser stops emitting data (just more error message) exists only in the XML parser." Me parece muy bien, pero esto no explica porque existe esa funcionalidad en el api de C. En los links del post hay un ejemplo de ésto.
Y para acabar unos enlaces interesantes:
- htmlParseChunk loop
- SAX HTML still stuck
- htmlParseFile vs htmlParseDoc
- Aborting html sax parsing from python
1 comentario:
Según veo, el html que se procesa es HTML 4.0 (sin validar).
Publicar un comentario