Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用XPath获取第二个元素文本?_Python_Xpath_Lxml - Fatal编程技术网

Python 使用XPath获取第二个元素文本?

Python 使用XPath获取第二个元素文本?,python,xpath,lxml,Python,Xpath,Lxml,我想把它组合成一个XPath表达式,只得到一个项目而不是一个列表 q = item.findall('.//span[@class="python"]//a') t = q[1].text # first element = 0 descendant::span[@class="python"]/descendant::a[2] 而实际的,不是简化的HTML是这样的 t = item.findtext('.//span[@class="python"]//a[2]') # first ele

我想把它组合成一个XPath表达式,只得到一个项目而不是一个列表

q = item.findall('.//span[@class="python"]//a')
t = q[1].text # first element = 0
descendant::span[@class="python"]/descendant::a[2]
而实际的,不是简化的HTML是这样的

t = item.findtext('.//span[@class="python"]//a[2]') # first element = 1

我不确定问题出在哪里

<span class='python'>
  <span>
    <span>
      <img></img>
      <a>google</a>
    </span>
    <a>chrome</a>
  </span>
</span>
从评论中:

或者简化实际的 我发布的HTML太简单了

你说得对。//span[@class=python]//a[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']
>>>
它将最终选择第二个子对象fn:position指的是子对象。因此,如果您的文档类似于:

self::node()
 /descendant-or-self::node()
  /child::span[attribute::class="python"]
   /descendant-or-self::node()
    /child::a[position()=2]
我试过了,但没用

q = item.findall('.//span[@class="python"]//a')
t = q[1].text # first element = 0
descendant::span[@class="python"]/descendant::a[2]
这是一个关于//缩写的常见问题解答

.//a[2]表示:选择当前节点的所有a子节点,这些子节点是其父节点的第二个a子节点。因此,这可能会选择多个元素或不选择任何元素,具体取决于具体的XML文档

更简单地说,[]运算符的优先级高于//

如果只需要返回所有节点中的第二个节点,则必须使用括号强制要求所需的优先级:

.//a[2]

这实际上选择了当前节点的第二个子节点

对于问题中使用的实际表达式,将其更改为:

(.//span[@class="python"]//a)[2]
或将其更改为:

(.//span[@class="python"]//a)[2]

您的表达式//span[@class=python]//a[2]适合我。嗯,我好像在什么地方出错了,或者我发布的实际HTML的简化太简单了。我会试着修改这个问题。@pdnsk:好问题,+1。有关解释和简单解决方案,请参见我的答案:很高兴你发布了这个问题。大约一天来,我们一直在试图解决类似的问题。它可以使用xpath,但不能使用findtext,并返回一个包含一项的列表。@pdknsk:这是因为此xpath表达式返回一个节点集结果:它可以是空的,也可以是单例的,可以是多个跨域的python类和第二个子体。。。如果需要此结果中第一个结果的字符串值,请使用此表达式作为参数的字符串函数。我不知道什么样的数据类型可以返回xpath方法……它可以工作。我将前面的答案与/text和这个答案结合使用,但我接受这个答案,因为它详细说明了问题。我只有一个问题。与/descandant::?@pdknsk:text的缩写等价物是什么?首先,text将返回所有text节点子节点。字符串或字符串值的DOM方法将返回所有子体文本节点的连接。不一样。第二,没有后代斧头的缩写形式。我的最后一个表达式,它等价于//span[@class=python]//a[2]?所以位置谓词应用于整个表达式,不仅仅是最后一步。谢谢你的解释,但我有一个问题,或者两个问题。如果只有一个匹配元素,[2]会抛出异常还是不返回异常?你知道为什么这适用于xpath而不适用于findtext吗?@pdnsk:我的答案是纯xpath。我不懂Python。我试过了,但它没有返回任何元素,这很好,因为我想避免使用列表并将其包含在单个表达式中的一个原因是没有额外的检查。我花了一整天的时间试图找出类似的答案。非常感谢你的帮助!
(.//span[@class="python"]//a)[2]/text()