J sports番組表

J sportsのサイトから番組表を取得する。HTMLにidやclassがちゃんとついてるので比較的楽にパースできる。次はこれをtwitterGoogle Calendarに投稿するようにしたい。

番組検索ページが返すHTMLはこんな感じ(一部)

<div id="resultArea">
<table width="670" border="0" cellspacing="0" cellpadding="0">
	<tr><th class="DRBoder">放送日程</th><th class="DRBoder">放送内容</th><th>放送チャンネル</th></tr>
<tr>
<td class="bSchedule">11月02日 (日) 25:00 - 28:00</td>
<td class="bContent">
<dl>

<dt class="ICON">&nbsp;</dt>
<dd class="DETAIL"><A href="/program/info/23510.html">ジロ・デ・イタリア2008 第15ステージ【153 km】(山岳ステージ) <br>アラッパ〜パッソ・フェダイア</a> <img src="../../shared/img/icon/img_dual.gif" alt="音声多重" width="14" height="13" /><img src="../../shared/img/icon/img_nonScramble.gif" alt="SKY!PerfecTVノースクランブル" width="14" height="13" /></dd>
</dl>
</td>
<td class="bChannel"><img src="img/ttl_one.gif" alt="J sports 1" width="90" height="12"></td>
</tr>

Rubyスクリプトは以下のような感じ。

$KCODE='u'

require 'rubygems'
require 'open-uri'
require 'hpricot'
require 'pp'
require 'nkf'
require 'date'

# 番組情報
class Program
  attr_accessor :from # 開始時間
  attr_accessor :to # 終了時間
  attr_accessor :title
  attr_accessor :channel
  attr_accessor :uri
    
  def initialize(schedule, detail, channel, uri)
    @from, @to = self.parseSchedule(schedule)
    @title = detail
    @channel = channel
    @uri = "http://www.jsports.co.jp" + (uri || "")
  end
  
  # 「11月02日 (日) 25:00 - 28:00」という表記をパース
  def parseSchedule(str)
    arr = str.gsub(" ", "").scan(/(\d+)(\d+)\(.*\)(\d+):(\d+)-(\d+):(\d+)/)[0]
    y = Date.today.year
    m, d, hf, mmf, ht, mmt = arr.map{|e| e.to_i}
    df, hf = correct(d, hf)
    dt, ht = correct(d, ht)
    dt = df if dt < df # 終了日がおかしい場合があるので修正
    [Time.mktime(y , m, df, hf, mmf), Time.mktime(y , m, dt, ht, mmt)]
  end
  
  # 25:00という記述を1:00、+1日へ直す
  def correct(day, hour)
    day += hour / 24
    hour = hour % 24
    [day, hour]
  end
end

# J sportsの番組検索ページから放送予定を取得、パースする。
class Parser
  def initialize(uri)
    @uri = uri # 番組検索ページのURI
  end
  
  def acquire
    programs = []
    doc = Hpricot.parse(NKF.nkf('-w', open(@uri).read))
    @result = doc.at("div#resultArea")
    @result.search("tr").each do |row|
      next unless row.at("td.bSchedule")
      programs << conv_program(row)
    end
    programs
  end
  
  def conv_program(row)
    sche = row.at("td.bSchedule").inner_text
    u = row.at("dd.DETAIL").at("a")["href"] if row.at("dd.DETAIL").at("a")
    detail = row.at("dd.DETAIL").inner_text
    chan = row.at("td.bChannel").at("img")["alt"]
    Program.new(sche, detail, chan, u)
  end

end

#psr = Parser.new("http://www.jsports.co.jp/search/sys/kensaku.cgi?Genre2=12")
#pp psr.acquire