パセラで曲検索
たまにカラオケに行くと、他の人が歌った曲で「いい曲だなー、あとでググろう」みたいなのが結構あります。
先日もカラオケに行ったんですが、普段なら気になった曲だけメモするところを、なぜか興に乗って全曲目を携帯でメモしてしまって。せっかくなので、そのメモを元に カラオケパセラ Σ-Search で検索を行うスクリプトを書いてみました。
携帯でのメモ
cagayake girls ふ・ほ super nova ぴ 嘘 ふ princess primp ほ :(以下略)
こんな感じで、曲名+スペース+歌った人をメモしてました。右側は歌った人の頭文字ですね。
スクリプト
汚いけど載せておきます。
$KCODE = "UTF8" # TODO: の置換とか require "nkf" require "open-uri" require "cgi" # URL サンプル # http://pasela.jp/search/pc/search.php?ss=%89R&line=0&lim=30 # 検索後は Shift_JIS で指定。 $url_format = 'http://pasela.jp/search/pc/search.php?ss=%s&line=0&lim=%s' columns = %w{No 歌った人 歌手名 タイトル 代表曲番号 歌い出し タイアップ ジャンル} # 検索実行 def simple_get(song, count) url = sprintf $url_format, CGI.escape(conv_song(song)), count open(url){|f| return NKF.nkf('-wS -m0', f.read) } end # 歌名検索時に邪魔な記号をスペースに置換 def conv_song(song) return song.gsub(%r{[\x20-\x2f\x3a-\x40\x5b-\x5f\x7b-\x7e〜・(×)]}, ' ') end # 歌った人の略称をちゃんとしたものに変換 def conv_singer(singer) return singer.sub(/ふ/, 'ふがさん'). sub(/ほ/, 'ほげさん'). sub(/ぴ/, 'ぴよさん') end puts columns.join("\t") DATA.each_with_index {|line, i| _, song, singer = */(.*) (.*)/.match(line) content = simple_get(song, 30) if content.match(%r{検索データが見つかりませんでした}) puts [ i+1, conv_singer(singer), song ].join("\t") next end count = content.slice(%r{検索結果:(\d+)曲}, 1) unless count puts "parse error at #{song}" print content break end if count.to_i > 30 content = simple_get(song, count) end content.scan(%r{<TR><TD>([^>]*)</TD><TD>([^>]*)</TD><TD>([^>]*)</TD><TD>([^>]*)</TD><TD>([^>]*)</TD><TD>([^>]*)</TD></TR>}){|m| m.unshift [ i+1, conv_singer(singer) ] puts m.join("\t") } sleep(1) } __END__ cagayake girls ふ・ほ super nova ぴ 嘘 ふ princess primp ほ :(以下略)
実際検索してみると、同じ曲名でもいろいろヒットするので、曲番号をメモしておけばよかったです・・・。
技術的なこと
もともと REXML で処理しようとしてたけど、パセラの検索結果ページが HTML なので REXML は使えないようで。HTML Tidy や HTML2XHTML とやらで valid XHTML に変換する方法もあるみたいだけど、どうも簡単じゃなさそうだったので、結局正規表現で適当に抽出しちゃいました。
その正規表現も、1.8 系だとちょっと貧弱な印象。練習がてら Ruby でやってみたけど、今度からこういう HTML を扱うときは、Perl か Python で書こう。
以前からの疑問
こういう「当日歌った曲目を参照できるサービス」みたいなのってカラオケ屋で提供されてないんでしょうか?割増料金で提供する形でも、後で曲目を DL できるようにしてアフィ貼り付けておくでも、店側の利益になりそうなのでやればいいと思うんですけど。