我不确定,但你的问题似乎出在 HTML 本身:请注意 有几个标签省略情况适用于
p
节点,因此段落的结束标签
<div class='thread'>
<p>first
<p>second</p>
</p>
</div>
简单地被解析器忽略,并且两个节点都被标识为兄弟节点,但不是父节点和子节点,例如
<div class='thread'>
<p>first
<p>second
</div>
所以 XPath
//div[@class="thread"]/p
会返回两个段落
您只需将
p
标签替换为 div
标签,您就会看到不同的行为:
<div class='thread'>
<div>first
<div>second</div>
</div>
</div>
这里
//div[@class="thread"]/div
将仅返回第一个节点
如果我的假设不正确,请纠正我
尝试这个 XPath 表达式:
//p[parent::div[@class='thread']]
或者用完整的Python表达式:
THREAD.xpath("//p[parent::div[@class='thread']]")
另一种(逆)方法是这个 XPath 表达式:
div[@class='thread']/child::p"
使用直接
child::
轴并且仅选择直接子节点。
总结:
两个表达式中哪一个更快取决于 XPath 编译器。
child::
是默认轴,如果没有给出其他轴则使用。
仅供参考:XPath 计数从 1 开始,并且 不是 0。
因此,关于您的 XML 示例,以下表达式
count(//div[@class='thread'][1]/child::p)
的结果是 2 - 计算
<p> <!-- 1 -->
+ <p><!-- 2 --></p>
的结果。
你可以尝试PARENT.getchildren()
>>> root = etree.fromstring(xml)
>>> root.xpath("//div[@class='thread']")[0].getchildren()
[<Element p at 0x10b3110e0>, <Element p at 0x10b311ea8>]