【问题标题】:What is the best way to parse this page using nokogiri?使用 nokogiri 解析此页面的最佳方法是什么?
【发布时间】:2011-06-02 20:37:37
【问题描述】:

我正在尝试找出解析由 25 个类似这样的重复卡盘组成的搜索结果屏幕的最佳方法:

姓名: JOHN DOE / COMPANY NAME

状态:活动

加入日期: 2007-08-17

地址: 123 MAIN STREET

城市: ANYTOWN 州/领地/其他: 纽约 国家/地区: 美国

邮政编码/邮政编码: 10101

我设法解析和清理页面以返回 25 个结果集之一,但我不知道如何返回其余结果集。我想实现一个从 9 增加到 33 的变量,但无法让它工作。我使用的代码如下所示:

require "nokogiri"           

class String
  def astrip
    self.gsub(/([\x09|\x0D|\n|\t])|(\xc2\xa0){1,}/u, '').strip
  end
end

i = 9

f = File.open("testpage.html", "r:iso-8859-1:utf-8")
doc = Nokogiri::HTML(f)

NAME        = doc.css(":nth-child(" + i.to_s + ") div:nth-child(1) a").text.astrip.split("/")
NAME_URL    = doc.css(":nth-child(" + i.to_s + ") div:nth-child(1) a").map { |link| link['href'] }
STATUS      = doc.css(":nth-child(" + i.to_s + ") div:nth-child(2) a").text
JOINED      = doc.css(":nth-child(" + i.to_s + ") div:nth-child(3)").text.gsub("Date Joined:", "").astrip.strip
ADDRESS1    = doc.css(":nth-child(" + i.to_s + ") div:nth-child(4)").text.gsub("Address:", "").astrip.strip
ADDRESS2    = doc.css(":nth-child(" + i.to_s + ") div:nth-child(5)").text.astrip.gsub("City:", "").gsub("State/Territory/Other", "").gsub("Country", "").split(":")
ZIPCODE     = doc.css(":nth-child(" + i.to_s + ") div:nth-child(6)").text.gsub("Postal Code/Zip Code:", "").astrip.strip

Output = NAME[0].strip, NAME[1].strip, NAME_URL[0].to_s.strip, STATUS, JOINED, ADDRESS1, ADDRESS2[0].strip, ADDRESS2[1].strip, ADDRESS2[2].strip, ZIPCODE

p Output

它返回一个我很满意的输出,如下所示:

["JOHN DOE", "COMPANY NAME", "http://linktoprofile/johndoe", "ACTIVE", "2007-08-17", "123 MAIN STREET", "ANYTOWN", "NEW YORK", "US", "10101"]

【问题讨论】:

  • 您的示例文本无助于确定如何访问各种标签。 Nokogiri 解析 XML 或 HTML,而不是文本,因此我们需要查看 HTML。

标签: ruby nokogiri


【解决方案1】:

如果没有示例 HTML,我们提供有效解决方案的能力非常有限。

这应该为您提供工作的起点:

require 'nokogiri'

html = <<EOT
<html>
  <body>
    <div>
      <p><b>Name:</b> JOHN DOE / COMPANY NAME</p>
      <p><b>Status:</b> ACTIVE</p>
      <p><b>Date Joined:</b> 2007-08-17</p>
      <p><b>Address:</b> 123 MAIN STREET</p>
      <p><b>City:</b> ANYTOWN <b>State/Territory/Other:</b> NEW YORK <b>Country:</b> US</p>
      <p><b>Postal Code/Zip Code:</b> 10101</p>
    </div>
  </body>
</html>
EOT

doc = Nokogiri::HTML(html)

data = doc.search('div').map { |div| 
  name               = div.at('//p[1]').text[/:(.+)/, 1].strip
  status             = div.at('//p[2]').text[/:(.+)/, 1].strip
  date_joined        = div.at('//p[3]').text[/:(.+)/, 1].strip
  address            = div.at('//p[4]').text[/:(.+)/, 1].strip
  city_state_country = div.at('//p[5]').text
  postal_code        = div.at('//p[6]').text[/:(.+)/, 1].strip

  city, state, country = (city_state_country.match(%r{City:(.+) State/Territory/Other:(.+) Country:(.+)}).captures).map{ |s| s.strip }

  {
    :name        => name,
    :status      => status,
    :date_joined => date_joined,
    :address     => address,
    :city        => city,
    :state       => state,
    :country     => country,
    :postal_code => postal_code
  }
}

生成的输出如下所示:

require 'pp'
pp data
# >> [{:name=>"JOHN DOE / COMPANY NAME",
# >>   :status=>"ACTIVE",
# >>   :date_joined=>"2007-08-17",
# >>   :address=>"123 MAIN STREET",
# >>   :city=>"ANYTOWN",
# >>   :state=>"NEW YORK",
# >>   :country=>"US",
# >>   :postal_code=>"10101"}]

如果你想要一个数组,在 map 块中使用它:

  [
    name,
    status,
    date_joined,
    address,
    city,
    state,
    country,
    postal_code
  ]

将生成:

# >> [["JOHN DOE / COMPANY NAME",
# >>   "ACTIVE",
# >>   "2007-08-17",
# >>   "123 MAIN STREET",
# >>   "ANYTOWN",
# >>   "NEW YORK",
# >>   "US",
# >>   "10101"]]

进行查找的另一种方法是:

data = doc.search('div').map { |div| 
  name,
  status,
  date_joined,
  address,
  city,
  state,
  country,
  postal_code = [
    'Name', 
    'Status', 
    'Date Joined', 
    'Address', 
    'City', 
    'State/Territory/Other', 
    'Country', 
    'Postal Code/Zip Code'
  ].map { |t| 
     div.at( %Q(//p/b[text()="#{t}:"]) ).next.text.strip
  }

【讨论】:

    猜你喜欢
    • 2010-09-14
    • 2012-07-02
    • 1970-01-01
    • 2015-06-14
    • 2011-09-05
    • 2019-09-16
    • 2021-05-31
    • 1970-01-01
    • 2011-11-30
    相关资源
    最近更新 更多