python - examples - requests-html
¿Cómo puedo analizar HTML con html5lib y consultar el HTML analizado con XPath? (7)
Estoy tratando de usar html5lib para analizar una página html en algo que puedo consultar con xpath. html5lib tiene documentación casi nula y he pasado demasiado tiempo tratando de resolver este problema. El objetivo final es sacar la segunda fila de una tabla:
<html>
<table>
<tr><td>Header</td></tr>
<tr><td>Want This</td></tr>
</table>
</html>
así que vamos a intentarlo:
>>> doc = html5lib.parse(''<html><table><tr><td>Header</td></tr><tr><td>Want This</td> </tr></table></html>'', treebuilder=''lxml'')
>>> doc
<lxml.etree._ElementTree object at 0x1a1c290>
Eso se ve bien, veamos que más tenemos:
>>> root = doc.getroot()
>>> print(lxml.etree.tostring(root))
<html:html xmlns:html="http://www.w3.org/1999/xhtml"><html:head/><html:body><html:table><html:tbody><html:tr><html:td>Header</html:td></html:tr><html:tr><html:td>Want This</html:td></html:tr></html:tbody></html:table></html:body></html:html>
LOL WUT?
seriamente. Estaba planeando usar algún xpath para obtener los datos que quiero, pero eso no parece funcionar. ¿Entonces Que puedo hacer? Estoy dispuesto a probar diferentes bibliotecas y enfoques.
Con BeautifulSoup , puedes hacer eso con
>>> soup = BeautifulSoup.BeautifulSoup(''<html><table><tr><td>Header</td></tr><tr><td>Want This</td></tr></table></html>'')
>>> soup.findAll(''td'')[1].string
u''Want This''
>>> soup.findAll(''tr'')[1].td.string
u''Want This''
(Obviamente ese es un ejemplo realmente crudo, pero ya.)
Dado que html5lib (de forma predeterminada) crea árboles que contienen (correcta) la información del espacio de nombres que ha especificado (los derechos) espacios de nombres en sus consultas, también.
Ejemplo con una consulta XPath:
import html5lib
inp=''''''<html>
<table>
<tr><td>Header</td></tr>
<tr><td>Want This</td></tr>
</table>
</html>''''''
xns = ''{http://www.w3.org/1999/xhtml}''
d = html5lib.parse(inp)
s = d.findall(''.//{}td''.format(xns))[-1].text
print(s)
Salida:
Want This
El mismo resultado sin XPath:
s = d.find(xns+''body'').find(xns+''table'').find(xns+''tbody'') /
.findall(xns+''tr'')[-1].find(xns+''td'').text
Alternativamente, también puede decirle a html5lib que evite agregar información de espacio de nombres durante el análisis:
d = html5lib.parse(inp, namespaceHTMLElements=False)
s = d.findall(''.//td'')[-1].text
print(s)
Salida:
Want This
La falta de documentación es una buena razón para evitar una IMO de la biblioteca, sin importar lo interesante que sea. ¿Estás casado con el uso de html5lib? ¿Has mirado lxml.html ?
Aquí hay una manera de hacer esto con lxml:
from lxml import html
tree = html.fromstring(text)
[td.text for td in tree.xpath("//td")]
Resultado:
[''Header'', ''Want This'']
Lo que desea utilizar es el argumento namespaceHTMLElements
, que por alguna razón se establece de manera predeterminada en True.
doc = html5lib.parse(''''''<html>
<table>
<tr><td>Header</td></tr>
<tr><td>Want This</td></tr>
</table>
</html>
'''''', treebuilder=''lxml'', namespaceHTMLElements=False)
print lxml.html.tostring(doc)
Sin embargo, es probable que aún sea más fácil usar lxml.html.
Siempre recomiendo probar la librería lxml
. Es increíblemente rápido y tiene muchas características.
También tiene soporte para el analizador html5lib si lo necesita: html5parser
>>> from lxml.html import fromstring, tostring
>>> html = """
... <html>
... <table>
... <tr><td>Header</td></tr>
... <tr><td>Want This</td></tr>
... </table>
... </html>
... """
>>> doc = fromstring(html)
>>> tr = doc.cssselect(''table tr'')[1]
>>> print tostring(tr)
<tr><td>Want This</td></tr>
creo que puedes hacer css search en objetos lxml ... asi
elements = root.cssselect(''div.content'')
data = elements[0].text
intenta usar jquery. y puedes recuperar todos los elementos. alternativamente, puedes poner una identificación en tu fila y sacarla.
1) ... ...
$ ("td") [1] .innerHTML será lo que quieras
2) ... ...
$ ("# blah"). text () será lo que quieras