RSSから条件に一致するエントリーだけを抽出するフィルター

idea:10544が上場しそうにないので、サンプル的なプログラムをRubyの勉強を兼ねて作ってみました。


RSS1.0を解釈して、title、link、dc:subject、dc:creatorに対して指定した正規表現パターンに一致するエントリーだけを抽出して再度RSSを構築します。

#! ruby 
 
require 'rss/1.0'
require 'rss/content'
require 'rss/trackback'
require 'rss/dublincore'
require 'rss/syndication'
require 'rss/maker'
 
class Grfeed
  attr :rss
  attr :title_tester, true
  attr :creator_tester, true
  attr :subject_tester, true
  attr :link_tester, true
  
  def initialize
    @rss = nil
    @title_tester = nil
    @creator_tester = nil
    @subject_tester = nil
    @link_tester = nil
  end
  
  def parse(rss_source)
    @rss = nil
    begin
      @rss = RSS::Parser.parse(rss_source, false)
    rescue RSS::InvalidRSSError
      @res = RSS::Parser.parse(rss_source, false)
    end
    rss
  end
  def restruct
    new_rss = RSS::Maker.make("1.0") do | maker |
      maker.channel.about = (@rss.channel.about || "none")
      maker.channel.title = (@rss.channel.title || "none")
      maker.channel.description = (@rss.channel.description || "none")
      maker.channel.link = @rss.channel.link
      maker.channel.dc_date = @rss.channel.dc_date if @rss.channel.dc_date
 
      @rss.items.each do | it |
        next unless test(it)
        item = maker.items.new_item
        item.link = it.link
        item.title = it.title
        item.description = it.description
        item.dc_creator = it.dc_creator
        it.dc_subjects.each do | subj |
          item.dc_subjects.new_subject.value=subj.value
        end
        item.dc_date = it.dc_date
      end
    end
    @rss = new_rss
  end
  def test(item)
    ret = true
    if (ret && @title_tester)
      ret = @title_tester.test(item.title)
    end
    if (ret && @creator_tester)
      ret = @creator_tester.test(item.dc_creator) 
    end
    if (ret && @subject_tester)
      subjects =  item.dc_subjects.collect{ |sj| sj.value.to_s }.sort.join(" ")
      ret = @subject_tester.test(subjects) 
    end
    if (ret && @link_tester)
      ret = @link_tester.test(item.link) 
    end
    ret
  end
  
  class Tester
    def initialize(pattern, inc=true, ignore=nil)
      @regexp = Regexp.new(pattern, ignore ? Regexp::IGNORECASE  : 0)
      @include = inc
    end
    def test(text)
      !(@regexp =~ text) ^ @include
    end
  end
end 

実際にこれを、レンタルサーバー上のCGIで動かせるようにしようとおもって、条件入力用HTML+JavascriptCGIインタフェース用のスクリプトも作ったのですが、サーバーにインストールされているrubyインタプリタのバージョンが1.8.2でrssパーザーのdc_subjectsメソッド*1が使えないことに最後になってから気づきました…orz
いや、それ以前にRSSにも広告を突っ込んでくれるみたいだ…。divで…。

追記

CGIへの広告挿入を回避する方法がわかったので、動かして見ました。

screenshot
http://sawat.jf.land.to/ruby/grfeed.html

RSS1.0のみ対応。複数dc:subjectには対応していません。RSS Auto-Discoveryなんかももちろん対応してません。

*1:rdf:RDF/item/dc:subjectタグを配列で取得する。1.8.4からサポート。これれがないと、はてなダイアリーのカテゴリーやはてなブックマークのタグが最初の一つしか抽出できない。