3

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

<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 />

我唯一的标签是<div>页面内容的周围。我想要的每一件事前面都有一个<span>Address</span>类型标签。它后面可以跟 anotherspan或 ahr结尾。

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

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

4

2 回答 2

5

使用Nokogiri 和 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"
# }

使用正确的解析器比使用正则表达式更容易、更健壮(这是一个有据可查的坏主意TM。)

于 2013-02-13T20:09:42.040 回答
0

我在考虑(相当学习)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')]

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

于 2013-02-13T22:55:32.930 回答