如何使用XPATH获取两个节点之间的所有元素?

时间:2015-04-11 09:39:39

标签: html xml xpath

我有这样的HTML代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>test</title>
    </head>
    <body>
        <h3><a href="#" name='title1'>Title</a></h3>
        <div>para1</div>
        <div>para2</div>
        <div>para3</div>
        <h3><a href="#" name='title2'>Title</a></h3>
        <div>para4</div>
        <div>para5</div>
    </body>
</html>

我想要的是:

<div>para1</div>
<div>para2</div>
<div>para3</div>

所以我想得到这个html的第一部分。我需要忽略第二部分。

现在我只是这样做:

#!/usr/bin/env python
# encoding: utf-8

import unittest

from lxml import etree

class SearchPara(unittest.TestCase):

    def setUp(self):
        with open('test.html') as f:
            self.html = f.read()

    def test_parse_html(self):
        paras = ''
        page = etree.HTML(self.html)
        a_ele = page.xpath("//h3/a[@name='title1']/..")

        if a_ele is None or len(a_ele) < 1:
            return paras

        para = a_ele[0].xpath('following-sibling::*[1][name(.) != "h3"]')
        while para is not None and len(para) > 0:
            print para
            paras += etree.tostring(para[0])
            para = para[0].xpath('following-sibling::*[1][name(.) != "h3"]')

        print paras


    def tearDown(self):
      pass

if __name__ == "__main__":
    unittest.main()

正如你所看到的,这有点复杂,如果我有办法做到这一点,我想知道什么?

1 个答案:

答案 0 :(得分:1)

据我所知,没有使用XPath 1.0在2个元素之间选择元素的一般方法。

如果我们能够以不同方式定义断言,仍然可以实现相同的输出。例如,选择<div> s,其中最近的兄弟<a>值等于"Title: Part I"

//div[preceding-sibling::a[1][. = 'Title: Part I']]

并选择下一个<div>组仅需要更改<a>条件:

//div[preceding-sibling::a[1][. = 'Title: Part II']]

查看上述xpath的测试方法:

def test_parse_html(self):
    page = etree.HTML(self.html)
    paras = ''
    para = page.xpath("//div[preceding-sibling::a[1][. = 'Title: Part I']]")
    for p in para:
        paras += etree.tostring(p)

    print paras

旁注。用于在代码中填充a_ele的xpath可以通过以下方式简化:

a_ele = page.xpath("//a[h3 = 'Title: Part I']")

或更进一步,因为<a>中唯一的文本元素是&#34;标题:第一部分&#34; :

a_ele = page.xpath("//a[. = 'Title: Part I']")