如何使用html5lib解析HTML,并使用XPath查询解析的HTML?

时间:2010-04-01 04:04:03

标签: python parsing xpath lxml html5lib

我正在尝试使用html5lib将html页面解析为可以使用xpath查询的内容。 html5lib文档接近零,我花了太多时间试图解决这个问题。最终目标是拉出表格的第二行:

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

所以试试吧:

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

看起来不错,让我们看看我们还有什么:

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

严重。我打算使用一些xpath来获取我想要的数据,但这似乎不起作用。那我该怎么办?我愿意尝试不同的图书馆和方法。

7 个答案:

答案 0 :(得分:20)

缺少文档是避免图书馆IMO的一个很好的理由,无论它有多酷。你是否坚持使用html5lib?你看过lxml.html吗?

以下是使用lxml执行此操作的方法:

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

结果:

['Header', 'Want This']

答案 1 :(得分:17)

您要使用的是namespaceHTMLElements参数,由于某种原因,该参数默认为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)

然而,使用lxml.html可能更容易。

答案 2 :(得分:3)

我总是建议试用lxml库。它速度极快,并且具有许多功能。

如果您需要,它还支持html5lib解析器: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>

答案 3 :(得分:2)

使用BeautifulSoup,您可以使用

执行此操作
>>> 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'

(显然这是一个非常粗糙的例子,但是你。)

答案 4 :(得分:1)

我相信你可以在lxml对象上进行css搜索..就像这样

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

答案 5 :(得分:0)

由于html5lib(默认情况下)创建包含(正确)命名空间信息的树,因此您也在查询中指定了(正确的)命名空间。

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)

输出:

Want This

没有XPath的结果相同:

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

或者,您也可以告诉html5lib避免在解析过程中添加任何名称空间信息:

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

输出:

Want This

答案 6 :(得分:-4)

尝试使用jquery。你可以检索所有元素。或者,您可以在行上放置一个ID并将其拉出来。

1)......

$(“td”)[1] .innerHTML将是你想要的

2)......

$(“#blah”)。text()将是你想要的