为了账号安全,请及时绑定邮箱和手机立即绑定

python,lxml或etree以获取包含某些文本的节点的父级

python,lxml或etree以获取包含某些文本的节点的父级

慕少森 2021-03-30 13:29:34
我如何继续获取包含一段文本的节点的父节点?此外,我可以使用一些正则表达式机制作为匹配元素进行搜索/过滤,re.compile("th[ei]s? .ne")例如从下面进行搜索?说 this onehtml = '''<html><head><title></title></head><body><table><tr><td>1a</td><td>2a</td><td>3a</td><td>4a</td><td>5a</td><td>6a</td></tr><tr><td>1b</td><td>2b</td><td>3b</td><td>4b</td><td>5b</td><td>6b</td></tr><tr><td>1c</td><td>2c</td><td>3c</td><td>4c</td><td>5c</td><td>6c this one</td></tr></table><div><div><table><tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr><tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr><tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr></table>this one</div></div></body></html>'''我想有一个返回的迭代器:<td>6c this one</td>进而:<div><table><tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr><tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr><tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr></table>this one</div>我试过:import lxml.htmlroot = lxml.html.document_fromstring(html)root.xpath("//text()[contains(., one)]")和import xml.etree.ElementTree as ETfor e in ET.fromstring(html).getiterator():    if e.text and e.text.find('one') != -1:        print "Found string %r, element = %r" % (e.text, e)但是我可以拥有的最好的节点是包含this one自身的节点...而我正在寻找包含此文本的父节点。请注意,div或表仅作为示例,我真的需要在找到“ this”之后返回到父级,而不是过滤包含的xml元素,this one因为在找到它之前,我将不知道这是div,表还是其他任何东西包含。
查看完整描述

3 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

根据示例输出,您似乎想要获取包含指定文本的元素one。您的描述说您想要该节点的父节点。

基于此假设,您可以使用以下XPath获得所需的节点:

//*[contains(text(), 'one')]

如果您确实想要此节点的父级,则可以执行

//*[child::*[contains(text(), 'one')]]

顺便说一句,如您所见,我使用谓词来获取节点,因此我过滤了XML节点。在我看来,这是更合乎逻辑和更易理解的方法,因为它基本上是说给我所有满足给定条件的节点,而不是说给我所有条件的输出,然后从这一点开始搜索实际所需的输出。但是您也可以执行以下操作,以更好地匹配您提出的解决方案:

//text()[contains(., 'one')]/parent::*


查看完整回答
反对 回复 2021-04-02
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

>>> root.xpath("//*[contains(child::*/text(), 'one')]") # why empty parent?

[]

该XPath表达式选择第一个孙文本节点包含“一个”的每个元素。的第一个参数contains()应为字符串,因此XPath接受结果中的第一个节点child::*/text()并采用其字符串值。由于没有元素的文本节点的第一个孙子节点包含“一个”,因此答案是空的节点列表。


>>> root.xpath("//*[contains(text(), 'one')]")

# i expected to have a list with two elements td and div

[<Element td at 0x280b600>]

出于相同的原因,此XPath表达式选择其第一个文本节点子代包含“一个”的所有元素。这就是为什么<td>选择<div>而不选择的原因:div的包含“一个”的子文本节点不是其第一个子文本节点。


>>> root.xpath("//*[child::*[contains(text(), 'one')]]")

# if parent: expected tr and div,

# if not parent expected table or div, still missing one

[<Element tr at 0x2821f30>]

这面临着与先前表达式相同的限制。


您是否尝试过@dirkk提出的最后一个解决方案,


//text()[contains(., 'one')]/parent::*

那应该避免将多个节点作为第一个参数传递给您的问题contains()。


查看完整回答
反对 回复 2021-04-02
  • 3 回答
  • 0 关注
  • 510 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号