使用lxml解析html提取嵌套元素中特定元素

4 投票
4 回答
2601 浏览
提问于 2025-04-15 21:35

大家好,我遇到了一些问题,我觉得可能是因为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]

撰写回答