Nokogiri一次解析多个XML提要并按日期排序

时间:2013-01-22 13:39:10

标签: ruby-on-rails ruby nokogiri

我正在使用Rails和Nokogiri来解析一些XML提要。

我已经解析了一个XML Feed,我想解析多个Feed并按日期对项目进行排序。它们是Wordpress提要,因此它们具有相同的结构。

在我的控制器中我有:

def index
  doc = Nokogiri::XML(open('http://somewordpressfeed'))  
  @content = doc.xpath('//item').map do |i| 
  {'title' => i.xpath('title').text, 'url' => i.xpath('link').text, 'date' => i.xpath('pubDate').text.to_datetime} 
  end
end

在我看来,我有:

<ul>
  <% @content.each do |l| %>
    <li><a href="<%= l['url'] %>"><%= l['title'] %></a> ( <%= time_ago_in_words(l['date']) %> )</li>
  <% end %>
</ul> 

上面的代码可以正常工作。我试图解析多个feed并得到404错误:

  feeds = %w(wordpressfeed1, wordpressfeed2)
  docs = feeds.each { |d| Nokogiri::XML(open(d)) }

如何解析多个Feed并将其添加到Hash中,就像我使用一个XML Feed一样?我需要在页面加载时一次解析大约50个XML提要。

1 个答案:

答案 0 :(得分:3)

我会用不同的方式写出来。

尝试更改index以接受一系列网址,然后使用map对其进行循环,将结果连接到您返回的数组:

def index(*urls)
  urls.map do |u|
    doc = Nokogiri::XML(open(u))  
    doc.xpath('//item').map do |i| 
      {
        'title' => i.xpath('title').text,
        'url' => i.xpath('link').text,
        'date' => i.xpath('pubDate').text.to_datetime
      } 
    end
  end
end

@content = index('url1', 'url2')

对于您的哈希键,使用符号而不是字符串会更像Ruby:

{
  :title => i.xpath('title').text,
  :url   => i.xpath('link').text,
  :date  => i.xpath('pubDate').text.to_datetime
} 

此外:

feeds = %w(wordpressfeed1, wordpressfeed2)
docs = feeds.each { |d| Nokogiri::XML(open(d)) }

each是错误的迭代器。您需要map,它将返回所有已解析的DOM,并将它们分配给docs

这不会修复404错误,这是一个错误的URL,并且是一个不同的问题。您没有正确定义数组:

%w(wordpressfeed1, wordpressfeed2)

应该是:

%w(wordpressfeed1 wordpressfeed2)

或:

['wordpressfeed1', 'wordpressfeed2']

编辑:

我正在重新访问此页面并注意到:

  

我需要在页面加载时一次解析大约50个XML Feed。

在处理从其他网站获取数据时,完全绝对是处理这种情况的错误方法,尤其是其中50个。

WordPress网站通常有新闻(RSS或Atom)Feed。 Feed中应该有一个参数说明刷新页面的确定频率。 HONOR,间隔并且不会经常访问其页面,特别是当您将负载绑定到HTML页面加载或刷新时。

原因有很多,但它会分解为“只是不要这样做”,以免被禁止。如果不出意外,使用网页刷新对您的网站进行DOS攻击是微不足道的,因此它会击败他们的网站,这对您来说都不是一个好的网络开发者。你先保护自己,然后继承自己。

那么,当你想要获得50个网站并且响应速度快而不打败其他网站时,你会怎么做?您将数据缓存在数据库中,然后在加载或刷新页面时从中读取数据。并且,在后台,您还有另一项任务,定期触发扫描其他站点,同时尊重其刷新率。