記事一覧はこちら

Rubyのコードを書いてみた

毎回毎回Eclipse立ち上げてjavaってのも大げさだし、実行ファイルとソースコードを両方管理しないといけないのは面倒。c#も同じく。 書き捨てのスクリプト言語では、今までphpを使っていたんだけど流石にあんまりなのでrubyを使ってみた。phpだとwindows上で日本語ファイルの扱いがめっちゃ面倒。 試しにOriconのサイトからランキングのデータを抜いてローカルに保存するコードを書いてみた。日時オブジェクトの操作、httpGetでの取得、正規表現取り扱い、ローカルに日本語unicodeファイルを作成、クラスの構文、例外を投げる書き方を試す。

require 'net/http'
require "date"
require 'json'
class OriconCdRanking
  def get( timeFromArg , timeToArg )
    timeFrom = getBeforeMonday( timeFromArg )
    timeTo   = getNextMonday( timeToArg )
    getOneDay( timeFrom )
  end
  # 前の月曜日を返す。引数が既に月曜日ならそれを返す
  def getBeforeMonday(timeArg)
    time=timeArg
    while time.monday? == false
      time  = time - 24*60*60
    end
    return time
  end
  # 次の月曜日を返す。引数が既に月曜日ならそれを返す
  def getNextMonday(timeArg)
    time=timeArg
    while time.monday? == false
      time  = time + 24*60*60
    end
    return time
  end
  def getOneDay( getTimeArg )
    # http://www.oricon.co.jp/rank/js/w/2015-05-04/p/2/
    if getTimeArg.monday? == false
      raise ArgumentError, "月曜日じゃない"
    end
    urlDate = getTimeArg.strftime("%Y-%m-%d")
    result = []
    for i in 1..5
      # urlPathを定義
      if i == 1 then
        urlPath = "/rank/js/w/%s/" % urlDate
      elsif
        urlPath = "/rank/js/w/%s/p/%d/" %  [ urlDate , i ]
      end
      responceStr = Net::HTTP.get('www.oricon.co.jp', urlPath)
      responceStr = responceStr.encode("UTF-8", "Shift_JIS")
      responceStr.scan(/<p class="num[^"]*">\d+<\/p>.+?<!-- \/.wrap-text -->/m) do |loopStr|
        matchRank  = loopStr[/<p class="num[^"]*">(\d+)<\/p>/,1] || ""
        matchImage = loopStr[/<img src="(.+?)"/,1] || ""
        matchTitle = loopStr[/<h2 class="title">(.+?)<\/h2>/,1] || ""
        matchLink  = loopStr[/class="inner"><a href=\"(.+?)\">/,1] || ""
        matchName  = loopStr[/<p class="name">(.+?)<\/p>/,1] || ""
        matchDate  = nil
        if loopStr[/<ul class="list">.*?<li>.*?発売日:.*?(\d+)年(\d+)月(\d+)日/m] then
          matchDate = Time.local( $~[1].to_i , $~[2].to_i , $~[3].to_i )
        end
        matchLabel = ( loopStr[/<ul class="list">.*?<li>.*?<\/li>.*?<li>(.+?)<\/li>/m,1] || "" ).strip
        oneData={ 
          :rank  => matchRank ,
          :image => matchImage ,
          :title => matchTitle ,
          :link  => matchLink ,
          :name  => matchName ,
          :date  => matchDate ,
          :label => matchLabel
        }
        result << oneData
        puts JSON.generate(oneData)
      end
    end
    File.open("結果 日本語 ❤.txt", "w") do |file|
      result.each{|resultLoop|
        file.puts(JSON.generate(resultLoop))
      }
    end
  end
end

t1 = Time.local(2015,1,2) 
t2 = Time.local(2015,12,1) 

a = OriconCdRanking.new()
a.get( t1 , t2 )

コードは未完成で、本当は指定した範囲の全部のランキングを取得するはずだったけど自重。日本語のファイル名を扱えるのが特にいいね。ちょっとした書き捨てスクリプトなら全然書けそう。ただクラスを定義してからじゃないと使えないのはちょっとな。一つのファイルに書こうとすると、クラスを書いた下にmain的な処理を書く必要があって見にくい気がする