読者です 読者をやめる 読者になる 読者になる

まめ畑

ゆるゆると書いていきます

mixiの日記を検索するスクリプトをRubyで書いてみた

Ruby mixi

はてだを見回ってたら、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["..."]

で取得しようとした時に、各日記のアドレスだけ表示されないという状態。
他のところはリンクがきちんと取得出来てた。


少し手間取った、もっと勉強必須