如何使用nokogiri找到具有共同最近祖先的相同深度的所有链接

Posted

技术标签:

【中文标题】如何使用nokogiri找到具有共同最近祖先的相同深度的所有链接【英文标题】:how to find all links at the same depth with a common closest ancestor with nokogiri 【发布时间】:2012-01-12 07:26:56 【问题描述】:
d=<<"EOM"
<ul>
  <li><a id=t href="t">a</a></li>
  <li><a id=b href="b">b</a></li>
  <li>
    <ul>
      <li><a href="inner">don't want inner</a></li>
      <li><a href="inner">don't want inner</a></li>
    </ul>
  </li>
  <li><a id=c href="c">c</a></li>
</ul>
<ul>
  <li><a href="d">don't want</a></li>
</ul>
EOM

doc = Nokogiri.html(d)
t = doc.css("#t")[0]

我怎样才能得到所有具有相同的href 外部容器为“t”并且在相同 深度为“t”?在这种情况下,我只想要 参考 t,b,c。 这些并不总是在 ul 中,只是使用 以它为例。

【问题讨论】:

【参考方案1】:

要获得所有具有相同“祖父母”的标签,您可以这样做:

doc.css('a').select|a| a.parent.parent == t.parent.parent

要获得他们的href:

doc.css('a').select|a| a.parent.parent == t.parent.parent.map|a| a[:href]

【讨论】:

【参考方案2】:

如果您知道 ID 将保持一致:

puts doc.search('#t, #b, #c').map |n| n['href'] 

如果您不知道它们会是什么,那么 XPath 可以帮助您:

doc.search('//*[@id="t"]/../../*/*[@id]').to_html
=> "<a id=\"t\" href=\"t\">a</a><a id=\"b\" href=\"b\">b</a><a id=\"c\" href=\"c\">c</a>"

doc.search('//*[@id="t"]/../../*/*[@id]').map |n| n['href'] 
=> ["t", "b", "c"]

意思是“找到id为't'的节点,然后倒退两层,往下看找到填充了id属性的节点”。

【讨论】:

【参考方案3】:

感谢@pguardiario

父节点可以在任何级别,所以我修改了你的代码:

 t = doc.css("#a")[0]
 r = []
 p = t.parent
 x = 0
 while true
   break if p.node_name == "body" || p.node_name == "html"
   x += 1
   r = doc.css('a').select|a| 
     m = a
     x.times  m = m.parent 
     m  == p
      
   break if r.length > 1
   p = p.parent
 end
 pp r.length

我确信有比这种蛮力方法更好的方法。

【讨论】:

以上是关于如何使用nokogiri找到具有共同最近祖先的相同深度的所有链接的主要内容,如果未能解决你的问题,请参考以下文章

查找具有特定类的最近的祖先元素

如何在任何二叉树中找到两个节点的最低共同祖先?

如何在任何二叉树中找到两个节点的最低共同祖先?

poj1330-----------关于公共祖先的问题

ZZNUOJ_C语言1110:最近共同祖先(函数专题)(完整代码)

找到两个Tree节点的最低共同祖先,而不参考root?