【问题标题】:Target text without tags using Nokogiri使用 Nokogiri 定位不带标签的文本
【发布时间】:2013-01-29 06:42:48
【问题描述】:

我尝试使用 Nokogiri(在 Ruby 上)解析一些非常简单的 HTML:

<span>Address</span><br />
123 Main Street<br />
Sometown<br />
<span>Telephone</span><br />
<a href="tel:212-555-555">212-555-555</a><br />

    <span>Hours</span><br />
    M-F: 8:00-21:00<br />
       Sat-Sun: 8:00-21:00<br />
<hr />

我唯一拥有的标签是围绕页面内容的&lt;div&gt;。我想要的每一件事前面都有一个&lt;span&gt;Address&lt;/span&gt; 类型标签。后面可以跟另一个span 或最后一个hr

我想将地址(“123 Main Street\nSometown”)、电话号码(“212-555-555”)和营业时间作为单独的字段来结束。

有没有办法使用 Nokogiri 获取信息,或者使用正则表达式更容易做到这一点?

【问题讨论】:

  • 将上面的文字分割成(?=&lt;span&gt;)?然后清理标签?
  • 使用 Nokogiri。总是,总是,总是使用解析器而不是正则表达式来处理 HTML/XML,除非你喜欢痛苦。
  • 你能发布你想要的输出吗?
  • @A.D.我在帖子中添加了一些信息。

标签: ruby regex nokogiri text-parsing


【解决方案1】:

我在考虑(相当学习)xpath:

d.xpath("span[2]/preceding-sibling::text()").each {|i| puts i}
# 123 Main Street
# Sometown

d.xpath("a/text()").text
# "212-555-555"

d.xpath("span[3]/following::text()").text.strip
# "M-F: 8:00-21:00       Sat-Sun: 8:00-21:00"

第一个从第二个跨度开始,然后选择之前的 text()。
您可以在这里尝试另一种方法 - 从第一个跨度开始,选择 text() 并以检查下一个跨度的谓词结束。

d.xpath("span[1]/following::text()[following-sibling::span]").each {|i| puts i}
# 123 Main Street
# Sometown

如果文档有更多跨度,您可以从正确的跨度开始:
span[x] 可以替换为span[contains(.,'text-in-span')]
span[3] == span[contains(.,'Hours')]

如果真的有问题,请纠正我。

【讨论】:

    【解决方案2】:

    使用Nokogiri and XPath 你可以这样做:

    def extract_span_data(html)
      doc = Nokogiri::HTML(html)
      doc.xpath("//span").reduce({}) do |memo, span|
        text = ''
        node = span.next_sibling
        while node && (node.name != 'span')
          text += node.text
          node = node.next_sibling
        end
        memo[span.text] = text.strip
        memo
      end
    end
    
    extract_span_data(html_string)
    # {
    #   "Address"   => "123 Main Street\nSometown",
    #   "Telephone" => "212-555-555",
    #   "Hours"     => "M-F: 8:00-21:00\n       Sat-Sun: 8:00-21:00"
    # }
    

    使用适当的解析器比使用正则表达式(即a well documented bad ideaTM)更容易且更健壮。

    【讨论】:

    • 感谢您的回答。因此,如果我理解的话,Nokogiri 会将由&lt;br&gt; 分隔的事物视为单独的节点?而只有memo 的行正在向reduce({}) 中给出的哈希添加条目?
    • 是的,在 XML/HTML 中,“节点”要么是标签及其内容,要么是文本块。所以"a&lt;br&gt;b" 将是三个节点,文本:“a”、元素:&lt;br&gt; 和文本:“b”。
    猜你喜欢
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    • 2017-12-14
    • 2010-10-26
    • 2016-09-06
    • 1970-01-01
    • 2021-07-21
    相关资源
    最近更新 更多