Pergunta

Estou tentando usar o html5lib para analisar uma página HTML em algo que posso consultar com o XPath. HTML5LIB tem quase zero documentação e passei muito tempo tentando descobrir esse problema. O objetivo final é retirar a segunda fila de uma mesa:

<html>
    <table>
        <tr><td>Header</td></tr>
        <tr><td>Want This</td></tr>
    </table>
</html>

Então vamos tentar:

>>> 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>

Isso parece bom, vamos ver o que mais temos:

>>> 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?

a sério. Eu estava planejando usar algum XPath para obter os dados que quero, mas isso não parece funcionar. Então o que eu posso fazer? Estou disposto a experimentar diferentes bibliotecas e abordagens.

Foi útil?

Solução

A falta de documentação é um bom motivo para evitar uma biblioteca IMO, por mais legal que seja. Você está casado para usar o html5lib? Você já olhou lxml.html?

Aqui está uma maneira de fazer isso com o LXML:

from lxml import html
tree = html.fromstring(text)
[td.text for td in tree.xpath("//td")]

Resultado:

['Header', 'Want This']

Outras dicas

O que você quer usar é o namespaceHTMLElements argumento, que por algum motivo o inadimplente é verdadeiro.

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)

Provavelmente ainda é mais fácil usar lxml.html.

Eu sempre recomendo experimentar lxml biblioteca. É incrivelmente rápido e tem muitos recursos.

Ele também tem suporte ao analisador HTML5LIB se precisar disso: 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>

Com Belo grupo, você pode fazer isso com

>>> 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, esse é um exemplo realmente grosseiro, mas sim.)

Eu acredito que você pode pesquisar CSS em objetos lxml .. como assim

elements = root.cssselect('div.content')
data = elements[0].text

Como o HTML5LIB (por padrão) cria árvores que contêm informações de namespace (corretas) que você especificar (a direita) também em suas consultas.

Exemplo com uma 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)

Resultado:

Want This

O mesmo resultado sem xpath:

s = d.find(xns+'body').find(xns+'table').find(xns+'tbody') \
     .findall(xns+'tr')[-1].find(xns+'td').text

Como alternativa, você também pode informar ao HTML5LIB para evitar adicionar qualquer informação para o nome de nome durante a análise:

d = html5lib.parse(inp, namespaceHTMLElements=False)
s = d.findall('.//td')[-1].text
print(s)

Resultado:

Want This

Tente usar o jQuery. E você pode recuperar todos os elementos. Como alternativa, você pode colocar um ID em sua linha e puxá -la para fora.

1) ... ...

$ ("td") [1] .innerhtml será o que você quer

2) ... ...

$ ("#blá"). Texto () será o que você quer

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top