Ruby で RSS 解析する際の覚え書き。

概要

Ruby 1.8.2 から RSS 解析ライブラリが標準搭載。

必要なもの

  1. Ruby 1.8.2 1.8.4
  2. Iconv

1.8.2 だと RSS::DublinCoreModel? に dc_subjects がないのでバージョンを上げた。

ラッパークラス サンプル

(get_rss.rb)

require 'rss/1.0'
require 'open-uri'

class RssSite
  attr_accessor:url
  attr_accessor:content
  attr_accessor:rss

  def initialize(url)
    @url = url
  end

  def get()
    @content = ""
    open(url) {|u|
      @content = u.read
    }

    parse()
  end

  def parse()
    begin
      @rss = RSS::Parser::parse(content)
    rescue RSS::InvalidRSSError
      @rss = RSS::Parser::parse(content,false)
    end
  end

  def save(file)
    File.open(file,'w') {|f|
      f.print(@content)
    }
  end

  def each_item
    rss.items.each {|i| yield(i) }
  end
end

class RSSTrace
  def initialize(url)
    @url = url
    @start = 0
    @max = 500
    @sep = 25
    @debugout = STDERR
  end
  
  def get
    @start.step(@max,@sep) {|i|
      b_url = "#{@url}&of=#{i}"
      
      r = RssSite.new b_url
      begin
        r.get
      rescue
        @debugout.puts $!
        next
      end
      @debugout.puts "get #{b_url}"
      
      r.rss.items.each {|i| yield i }
    }
  end
  
  attr_accessor :url, :start, :max, :sep, :debugout
end

使い方

C:\>irb
irb(main):001:0> require 'get_rss.rb'
=> true
irb(main):002:0> r = RssSite.new("http://internet.kill.jp/int.rdf")
=> #<RssSite:0x2ff4d48 @url="http://internet.kill.jp/int.rdf">
irb(main):003:0> r.get
=> (略)
irb(main):004:0> r.save("int.rdf")
=> nil
irb(main):005:0> r.url = "int.rdf"
=> "int.rdf"
irb(main):006:0> r.get
=> (略)

このように、ネットワークとローカルファイルはほぼシームレス。 open-uri すごい。

応用

2006-10-18

拡張クラス RSSTrace を作ってみた。 事実上ほとんどはてな用だけど、はてなブックマークの RSS のように位置を指定しながら次々取っていくインターフェースのトレーサ。 get メソッドの引数にブロックを渡すと RSS の item ごとに評価します。

http://b.hatena.ne.jp/xx-internet/ のブックマーク URL を最大 10000 件表示するサンプル。

require 'get_rss.rb'
t = RSSTrace.new("http://b.hatena.ne.jp/xx-internet/rss?")
t.max = 10000
t.get {|item| puts item.link }

2006-03-18

404 blog not found - 最近のはてブで流行している7つのタグを見て追試。

はてブの RSS は dc:subject にタグが書いてあるので、以下のようにしてみた。

require 'get_rss'
require 'rss/dublincore'

r = RssSite.new("http://b.hatena.ne.jp/entrylist?mode=rss&sort=hot&threshold=5")
r.get()
r.save("hb_hot.xml")

r.rss.items.each{|i|
  i.dc_subject.each{|s|
    puts s.content
  }
}

NG 。これだと最初の dc_subject しか取っていない。 軽く調べて dc_subjects を使えばいいらしい、 と知り、そっちを使う。(ついでに Ruby 自体を 1.8.2 -> 1.8.4 にアップデートしてしまった)

r.rss.items.each{|i|
  i.dc_subjects.each{|s|
    puts s.content
  }
}

これでなんとなく動いたので、ロジックをいじって完成。なんだかんだで一時間以上かかった。

r = RssSite.new( "http://b.hatena.ne.jp/hotentry?mode=rss")
r.get()
r.save("hb_hotentry.xml")

tags = Hash.new {|hash,key| hash[key] = 0 }

r.rss.items.each{|i|
  begin
    r_entry = RssSite.new( 'http://b.hatena.ne.jp/entry/rss/' + i.link)
    puts "get #{r_entry.url}"
    r_entry.get()
    r_entry.rss.items.each{|j|
      j.dc_subjects.each{|s|
        tags[s.content] += 1
      }
    }
  rescue
    STDERR.puts $!
  end
}

tags.to_a.sort{|a, b|
  (b[1] <=> a[1]) * 2 + (a[0] <=> b[0])
}.each {|key, item|
  puts "#{key}  #{item}"
}
javascript	176
web	141
2ch	93
sns	89
prototype.js	85
ajax	83
design	73
SNS	55
JavaScript	52
webデザイン	52

またちょっと結果が違う。

あと、 get_rss.rb の parse 部分を別メソッドにしてみた。 こうすると

r.get()

# あ、 DublinCore のデータ欲しい
require 'rss/dublincore'

# 再解析
r.parse()

というふざけた使い方が可能に。

参考リンク

COZMIXNG RWiki -RSS Parser
標準 RSS パーサの使い方。
Nowhere Near - MM/Memo の内容をはてなブックマークへ同期
RSS 取得部分を参考にさせていただいた。

更新履歴

  • 2006-10-18 RSSTrace クラスを追加。
  • 2006-09-03 each_item メソッドを追加。

最新の10件を表示しています。 コメントページを参照

  • hpvdbNNp -- srwruxxqwsf? 2010-04-23 (金) 03:13:31
お名前:

添付ファイル: filehb_hot_tags.zip 838件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2006-10-19 (木) 07:17:37 (1415d)