【问题标题】:Retrieving text between <br> in Rails + Nokogiri在 Rails + Nokogiri 中检索 <br> 之间的文本
【发布时间】:2012-12-21 21:49:50
【问题描述】:

对于以下部分 HTML,我正在尝试检索文本“进行研究......找到治疗方法!”通过 Nokogiri 在两个 &lt;br&gt; 标签之间。

<b>Multiple Sclerosis National Research Institute</b><br>
<!-- <b>CFC Code: 12135</b><br />     ***** This is edited by Anas -->
<a href="http://www.ms-research.org" target="_blank">http://www.ms-research.org</a><br> 
(866)-676-7400<br> 
Conducts research towards understanding, treating and halting the progression of multiple sclerosis and related diseases. Current research progress is promising. Please help us find cures!<br>
<a href="/ntn/charities/view.aspx?record_id=510">Click here for more info</a><br><br>

到目前为止,我已经能够使用以下代码检索 nameurl

url = "https://www.neighbortonation.org/ntn/charities/home.aspx"    
doc = Nokogiri::HTML(open(url))

doc.css("#site-pagecontent table table td").each do |item|
    name = item.at_css("b").text unless item.at_css("b").blank?
    url = item.at_css("a")[:href] unless item.at_css("a").blank?
end

但我在尝试检索特定 &lt;br&gt; 标记之间的文本时遇到了困难。我通过Extracting between <br> tags with Nokogiri? 尝试了这些建议,但这似乎不起作用。有任何想法吗?我应该使用 xpath、搜索还是正则表达式?

【问题讨论】:

    标签: ruby ruby-on-rails-3 nokogiri


    【解决方案1】:

    这个怎么样:

    html = '<b>Multiple Sclerosis National Research Institute</b><br> ...'
    doc = Nokogiri::HTML(html)
    doc.css('br')[2].next.text.strip
    #=> "Conducts research towards understanding, treating and halting the progression of multiple sclerosis and related diseases. Current research progress is promising. Please help us find cures!"
    

    还有直播内容:

    url = "https://www.neighbortonation.org/ntn/charities/home.aspx"    
    doc = Nokogiri::HTML(open(url))
    
    doc.css("#site-pagecontent table table td").each do |item|
      description = item.css('br')[2].next.text.strip unless item.css('br').empty?
      ...
    end
    

    【讨论】:

    • 创造奇迹!谢谢。你能解释一下这是做什么的吗?我不熟悉地图的工作原理。
    • Array#map 遍历数组,将每个值产生给块并创建一个新数组。无论块返回什么都用作该值的“替换”项。在这种情况下,&amp;:next{ |item| item.next } 相同;它创建一个块,对数组的值调用next 方法并计算结果。所以,解码上面的答案说“找到所有&lt;br&gt;作为一个数组,然后用the next item替换每个。现在找到其中的第三个,然后获取文本,然后去掉外面的空白。
    • 一些建议:1) 选择第三个&lt;br&gt; 可能适用于这个特定的文本 sn-p,但它似乎非常脆弱。我更喜欢尝试基于实体内容进行锚定(请参阅我的答案)。 2) 与其查找所有doc.css('br').map(&amp;:next)[2].text,我建议使用更简单、更高效的doc.css('br')[2].next.text。在您最终不关心的所有&lt;br&gt; 中,没有理由找到next
    • @Phrogz 感谢您的建议!我也担心选择第二个元素的脆弱性,但我在链接上对其进行了测试并且它有效,所以我认为它会做。也感谢我同意并采纳的第二个建议。
    • 谢谢,现在这更有意义了。我认为 Nokogiri 文档可以使用一些帮助。
    【解决方案2】:

    当谈到 XML 中的“元素之间的文本”时,记住 XML 中的文本保存在 Text node 中会有所帮助。在 Nokogiri 中,这是一个 Nokogiri::XML::Text 实例。

    例如,这个 HTML:

    <p>Hello <b>World</b>!</p>
    

    最简单的表示为:

    (Element name:"p" children:[
      (Text content:"Hello ")
      (Element name:"b" children:[
        (Text content:"World")
      ])
      (Text content:"!")
    ])
    

    &lt;p&gt; 元素具有三个子节点。通常我们不需要记住这一点,因为我们经常想知道文本是孩子还是后代,找到一个元素然后使用.text 方法给我们一个字符串。

    在您的情况下,您希望找到最可靠的方法来定位附近的元素。让我们假设&lt;a href="..."&gt;Click here for more info&lt;/a&gt; 将始终存在,并且您想要的文本就在它之前。

    # Find an <a> element with specific text content
    info = doc.at_xpath('//a[.="Click here for more info"]')
    
    # Walk back to the previous element, which we assume is an always-present <br>
    br   = info.previous_element
    
    # Find the Text node immediately preceding that, and then get its contents
    desc = br.previous.text
    

    我们可以使用 XPath 更高效、更简洁地做到这一点,但 Ruby 程序员更难理解:

    p doc.at('//a[.="Click here for more info"]/preceding-sibling::text()[1]').text
    #=> " \nConducts research towards understanding, treating and halting the ...
    

    上面找到锚点,然后使用 XPath 查找所有前面的文本节点,然后只选择第一个文本节点。

    【讨论】:

    • 这太棒了!谢谢弗罗兹!
    猜你喜欢
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多