使用lxml解析html提取嵌套元素中特定元素
大家好,我遇到了一些问题,我觉得可能是因为xpath的原因。我正在使用lxml包中的html模块来获取一些数据。下面是我简化后的情况,但请记住,我处理的html要复杂得多。
<table>
<tr>
<td>
<table>
<tr><td></td></tr>
<tr><td>
<table>
<tr><td><u><b>Header1</b></u></td></tr>
<tr><td>Data</td></tr>
</table>
</td></tr>
</table>
</td></tr>
</table>
我真正想要的是那个嵌套很深的表格,因为它有一个标题文本“Header1”。我尝试这样做:
from lxml import html
page = '...'
tree = html.fromstring(page)
print tree.xpath('//table[//*[contains(text(), "Header1")]]')
但是这样会给我所有的表格元素。我只想要包含这个文本的那个表格。我明白发生了什么,但我很难找到解决办法,除了使用一些复杂的正则表达式。你们有什么想法吗?
4 个回答
0
也许这个方法对你有用:
tree.xpath("//table[not(descendant::table)]/*[contains(., 'Header1')]")
这里的 not(descendant::table)
这一部分是用来确保你得到的是最里面的那个表格。
2
找到你感兴趣的标题,然后提取它的表格。
//u[b = 'Header1']/ancestor::table[1]
或者
//td[not(.//table) and .//b = 'Header1']/ancestor::table[1]
注意,//
总是从文档的根部开始(!)。你不能这样做:
//table[//*[contains(text(), "Header1")]]
然后期待里面的条件(//*…
)能神奇地从正确的上下文开始。应该使用.//
来从当前节点开始。即便如此,这样做:
//table[.//*[contains(text(), "Header1")]]
也不会有效,因为即使是最外层的表格里面也包含了文本'Header1'
,而且这个文本可能在很深的地方,所以在你的例子中,条件对每个表格都成立。像我一样使用not()
来确保没有其他表格是嵌套的。
另外,不要在每个节点上测试条件.//*
,因为一开始就不可能对每个节点都成立。具体一点会更有效。
3
使用方法:
//td[text() = 'Header1']/ancestor::table[1]