<span class='python'>
<a>google</a>
<a>chrome</a>
</span>
我想获得chrome
并让它像这样工作。
q = item.findall('.//span[@class="python"]//a')
t = q[1].text # first element = 0
我想把它组合成一个XPath表达式,只得到一个项目而不是列表。
我尝试了这个但它不起作用。
t = item.findtext('.//span[@class="python"]//a[2]') # first element = 1
实际的,不是简化的HTML是这样的。
<span class='python'>
<span>
<span>
<img></img>
<a>google</a>
</span>
<a>chrome</a>
</span>
</span>
答案 0 :(得分:34)
我尝试了这个,但它不起作用。
t = item.findtext('.//span[@class="python"]//a[2]')
这是关于//
缩写的常见问题解答。
.//a[2]
表示:选择当前节点的所有a
后代,这些后代是其父级的第二个a
子级。因此,这可能会选择多个元素或没有元素 - 具体取决于具体的XML文档。
更简单地说,[]
运算符的优先级高于//
。
如果您只想返回所有节点中的一个(第二个),则必须使用括号来强制您想要的优先级:
(.//a)[2]
这确实选择了当前节点的第二个a
后代。
对于问题中使用的实际表达式,请将其更改为:
(.//span[@class="python"]//a)[2]
或将其更改为:
(.//span[@class="python"]//a)[2]/text()
答案 1 :(得分:2)
我不确定问题是什么......
>>> d = """<span class='python'>
... <a>google</a>
... <a>chrome</a>
... </span>"""
>>> from lxml import etree
>>> d = etree.HTML(d)
>>> d.xpath('.//span[@class="python"]/a[2]/text()')
['chrome']
>>>
答案 2 :(得分:2)
来自评论:
或实际的简化 我发布的HTML太简单了
你是对的。 .//span[@class="python"]//a[2]
是什么意思?这将扩展为:
self::node()
/descendant-or-self::node()
/child::span[attribute::class="python"]
/descendant-or-self::node()
/child::a[position()=2]
最终会选择第二个a
孩子(fn:position()
引用child
斧头)。因此,如果您的文档如下,则不会选择任何内容:
<span class='python'>
<span>
<span>
<img></img>
<a>google</a><!-- This is the first "a" child of its parent -->
</span>
<a>chrome</a><!-- This is also the first "a" child of its parent -->
</span>
</span>
如果您想要所有后代中的第二个,请使用:
descendant::span[@class="python"]/descendant::a[2]