gpt4 book ai didi

ruby-on-rails - 如何使用 Nokogiri 导航 DOM

转载 作者:数据小太阳 更新时间:2023-10-29 06:57:45 26 4
gpt4 key购买 nike

我正在尝试填充变量 parent_element_h1parent_element_h2 .谁能帮我用Nokogiri将我需要的信息获取到这些变量中?

require 'rubygems'
require 'nokogiri'

value = Nokogiri::HTML.parse(<<-HTML_END)
"<html>
<body>
<p id='para-1'>A</p>
<div class='block' id='X1'>
<h1>Foo</h1>
<p id='para-2'>B</p>
</div>
<p id='para-3'>C</p>
<h2>Bar</h2>
<p id='para-4'>D</p>
<p id='para-5'>E</p>
<div class='block' id='X2'>
<p id='para-6'>F</p>
</div>
</body>
</html>"
HTML_END

parent = value.css('body').first

# start_here is given: A Nokogiri::XML::Element of the <div> with the id 'X2
start_here = parent.at('div.block#X2')

# this should be a Nokogiri::XML::Element of the nearest, previous h1.
# in this example it's the one with the value 'Foo'
parent_element_h1 =

# this should be a Nokogiri::XML::Element of the nearest, previous h2.
# in this example it's the one with the value 'Bar'
parent_element_h2 =

请注意:start_here元素可以在文档中的任何位置。 HTML 数据只是一个例子。也就是说,标题 <h1><h2>可能是 start_here 的 sibling 或 start_here 的 sibling 的 child .

以下递归方法是一个很好的起点,但它不适用于 <h1>因为它是 start_here sibling 的 child :

def search_element(_block,_style)
unless _block.nil?
if _block.name == _style
return _block
else
search_element(_block.previous,_style)
end
else
return false
end
end

parent_element_h1 = search_element(start_here,'h1')
parent_element_h2 = search_element(start_here,'h2')

接受答案后,我想出了 my own solution .它就像一个魅力,我认为它非常酷。

最佳答案

我将采用的方法(如果我理解您的问题)是使用 XPath 或 CSS 来搜索您的“start_here”元素和您要在其下搜索的父元素。然后,从父级开始递归遍历树,当您点击“start_here”元素时停止,并沿途保留与您的风格相匹配的最后一个元素。

类似于:

parent = value.search("//body").first
div = value.search("//div[@id = 'X2']").first

find = FindPriorTo.new(div)

assert_equal('Foo', find.find_from(parent, 'h1').text)
assert_equal('Bar', find.find_from(parent, 'h2').text)

其中 FindPriorTo 是处理递归的简单类:

class FindPriorTo
def initialize(stop_element)
@stop_element = stop_element
end

def find_from(parent, style)
@should_stop = nil
@last_style = nil

recursive_search(parent, style)
end

def recursive_search(parent, style)
parent.children.each do |ch|
recursive_search(ch, style)
return @last_style if @should_stop

@should_stop = (ch == @stop_element)
@last_style = ch if ch.name == style
end

@last_style
end

end

如果这种方法的可扩展性不够,那么您可以通过重写 recursive_search 以不使用递归来优化事情,同时传入您正在寻找的两种样式并保留最后找到的 rails ,因此您不必额外遍历树。

我还想尝试猴子修补 Node,以便在解析文档时 Hook ,但看起来所有这些都是用 C 编写的。也许使用具有原生 Ruby 的 Nokogiri 以外的东西可能会更好SAX 解析器(可能是 REXML ),或者如果您真正关心速度,请使用 Xerces 或类似工具在 C/C++ 中执行搜索部分。不过,我不知道这些在解析 HTML 方面的表现如何。

关于ruby-on-rails - 如何使用 Nokogiri 导航 DOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/657468/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com