mixiの日記を検索するスクリプトをRubyで書いてみた
はてだを見回ってたら、mixiで指定ユーザーの日記を全文検索するプログラム作った!! - テックノート@ama-chというのを見つけました。
なんか便利そうなのでRubyの練習ついでに書いてみた。多謝。
汚いし、Rubyらしくない雰囲気悶々とするけど動作してます。
使い方などはほとんど同じです。
require 'rubygems' require 'mechanize' require 'hpricot' require 'kconv' $KCODE = 'UTF8' BASE_URL = 'http://mixi.jp/' NIKKI_LIST = BASE_URL + 'list_diary.pl' DEFO = とりあえず検索したい人 MAIL = "メール" PASS = "パスワード" #ファイル関係を処理 def create_data_file(id) $file_name = "diary-#{id}.dump" if File.exist?($file_name) puts "LOADING..." $title = Marshal.load(open($file_name, "rb"))[0] $body = Marshal.load(open($file_name, "rb"))[1] $newest = Marshal.load(open($file_name, "rb"))[2][0].to_i else puts "NEW FILE" $title = {} $body = {} $newest = 0 end end #ログイン処理 def login $agent = WWW::Mechanize.new $agent.max_history = 1 $agent.user_agent_alias = 'Windows IE 6' login = $agent.get(BASE_URL) login_form = login.forms[0] login_form["email"] = MAIL login_form["password"] = PASS $agent.submit(login_form) end #日記の取得 def get_nikki(id, page=1) flag = false print "id:#{id}の#{page}ページ目を取得開始します\n" nikki_list = Kconv.toutf8($agent.get(NIKKI_LIST+"?page=#{page}&id=#{id}").body) lists = nikki_list.scan(/view_diary.pl\?id=(\d+)&owner_id=\d+/).uniq #intに直す $listsi = [] lists.each do |list| $listsi << list[0].to_i end #各日記の本文などを取得 $listsi.each do |list| if list[0].to_i > $newest flag = true nikki = Kconv.toutf8($agent.get(BASE_URL+"view_diary.pl?id=#{list}&owner_id=#{id}").body) #日付をi取得 date = nikki.scan(/<dd>(\d{4})年(\d{2})月(\d{2})日(\d{2}:\d{2})<\/dd>/).join("/") #タイトルを取得 $title[date] = nikki.scan(/\[mixi\] (.+)<\/title>/)[0] #本文を取得 $body[date] = nikki.scan(/\"diary_body\">([\s\S]+)<\/div>\n<script/)[0] sleep 2 end end $body.keys.each do |key| begin $body[key] = $body[key][0].gsub("<br />", "\n") rescue #エラー end end if !flag puts "変更なし" return elsif flag && $newest != 0 $newest = $listsi.max puts "更新しました->#{$newest}" elsif nikki_list.scan(/<a href="list_diary.pl?.*">次を表示<\/a>/)[0] sleep 1 get_nikki(id, page+1) else $newest = $listsi.max puts "最新をセット->#{$newest}" end end #いろいろ検索 def search(num) if num == "1" print "yyyy/mm/ddを入力してください:" date = gets.chop hits = 0 $title.keys.each do |key| if key.rindex(date) hits = hits+1 puts key.to_s + " , " + $title[key][0] puts $body[key] end end puts "#{hits}件ヒットしました" elsif num == "2" print "検索文字列を入力してください: " word = gets.chop hits = 0 $title.keys.each do |key| if $title[key].rindex(word) || $body[key].rindex(word) hits = hits+1 puts key.to_s + " , " + $title[key][0] puts $body[key] end end puts "#{hits}件ヒットしました" elsif num == "3" hits = 0 $title.keys.sort.each do |key| puts key.to_s + " , " + $title[key][0] puts $body[key] end elsif num == "4" exit else puts "えらーーーーーーーー" end end print "誰を探す?: " mixiid = gets.chop mixi_id = (mixiid == "")? DEFO : mixiid create_data_file(mixi_id) login get_nikki(mixi_id) #シリアライズ nikkis = [$title, $body, $newest] File.open($file_name,"wb"){|f| Marshal.dump(nikkis, f) } while(1) print "\n1:指定日の日記 2:全文検索 3:全日記表示 4:終了\n" print "# " input = gets.chop search(input) end
アドバイスなどありましたらお願いします。
今回勉強したこと
Marshal.loadとdump。
Javaではシリアライズしたことあったけど、Rubyのほうが簡単だ。
やっぱRubyかわいいよ。
これは便利だな、使えそうだ。
DBにぶち込んでも良かったけど、今以上に実験用DBにデータベースは厳しいのでこれでやってみた。
Protocol Bufferも使ってみたいな。
今、Javaで原因不明なエラーで止まってる。
解決次第エントリーに投下しよう。
不明な点(勉強するとこ)
File.open(hoge, "rb"){|f| hoge = Marshal.load(f)[0] piyo = Marshal.load(f)[1] }
とすると、2個目でファイルが閉じてるとエラー。
かといって、読み取り位置を先頭に移動しても同じ、なにかうまい方法ないかな。
いちいち開いてるとコストかかるし。
あとは、日記の一覧から各日記のアドレスを取得するさいに、
hoge = agent.get("....")
hoge.links.href["..."]
で取得しようとした時に、各日記のアドレスだけ表示されないという状態。
他のところはリンクがきちんと取得出来てた。
少し手間取った、もっと勉強必須