livedoor Readerとクリップのバックアップ

はてなで書くことでない気もするが、rubyのWWW::mechanizeを使って、livedoor Readerとクリップのバックアップを取るコマンドを何となく作ってみた。

WWW::mechanizeとgemが必要なので、http://d.hatena.ne.jp/samurai20000/20070218/1171792732の手順のまま設定する必要がある。

使い方

設定ファイルlivedoor.conf書く
#ログインID
@userid = "ididid"
#パスワード
@password = "passpasspass"
#cookieファイル名(cookieを無効にするならコメントアウト)
#@cookie_file = "lbdcookie"
#livedoor readerの保存ファイル名
@reader_file = "reader.xml"
#livedoor clipの保存ファイル名
@clip_file = "clip.xml"
Readerとクリップの両方をバックアップ
./livedoorreader.rb
Readerをバックアップ
./livedoorreader.rb -r
クリップをバックアップ
./livedoorreader.rb -c

とりあえず、cygwin上で動作することは確認しました。
vmware上のdebianで試すと、コマンドオプションなしで使うとWWW::Mechanizeの中でエラーが発生してしまう。コマンドオプションをつけて、1つずつ取得するときには問題ない。う〜ん、よくわからん。

深く考えずに作ってみたので、良くないところがあるのはわかっている。特に、現時点のサイト構成URLで取得しているのが良くない。livedoor側がURL等を変えるだけで動かなくなる。

あと、cookieの実装については、http://d.hatena.ne.jp/sshi/20080115を参考にさせてもらった。

#!/usr/bin/ruby

require 'rubygems'
require 'mechanize'
require "optparse"
require 'kconv'


# 設定を外部ファイルに保存する
class ConfigLive
  attr_reader :userid
  attr_reader :password
  attr_accessor :opt_clip
  attr_accessor :opt_reader
  attr_reader :cookie_file
  attr_reader :clip_file
  attr_reader :reader_file
  def initialize
    # デフォルト設定
    @reader_file = "livedoor_reader.xml"
    @clip_file = "livedoor_clip.xml"
  end
  def ConfigLive.load(fpath)
    c = new()
    c.instance_eval File.read(fpath)
    return c
  end

end

class LiveDoor
  def initialize(config)
    @id = config.userid
    @password = config.password
    @agent = WWW::Mechanize.new
    @reader = config.opt_reader
    @clip = config.opt_clip
    @cookie_file = config.cookie_file
    @reader_file = config.reader_file
    @clip_file = config.clip_file
  end
  def login
    unless !@cookie_file.nil? && FileTest.exist?(@cookie_file)
      login_page = @agent.get("http://reader.livedoor.com/reader/")
      login_form = login_page.forms.name("loginForm").first
      login_form['livedoor_id'] = @id
      login_form['password'] = @password
      @agent.submit(login_form)
      logf = login_check
      if logf
        unless @cookie_file.nil?
          @agent.cookie_jar.save_as(@cookie_file)
        end
      end
    else
      @agent.cookie_jar.load(@cookie_file)
    end
  end
  def login_check
    edit_page = @agent.get("http://reader.livedoor.com/reader/")
    edit_page.forms.name('loginForm').first == nil
  end
  def save
    if @reader
      sv_reader
    end
    if @clip
      sv_clip
    end
    unless @reader || @clip
      sv_reader
      sv_clip
    end
  end
  private
  def sv_reader
    File.open(@reader_file, "w") { |file|
      x = @agent.get_file("http://reader.livedoor.com/export/opml")
      file.write(x)
    }
  end
  def sv_clip
    File.open(@clip_file, "w") { |file|
      x = @agent.get_file("http://clip.livedoor.com/export/export?mode=rss")
      file.write(x)
    }
  end
end

config = ConfigLive.load("livedoor.conf")
parser = OptionParser.new
parser.banner = "Usage: #{File.basename($0)} [options]"
parser.on("-c", "backup livedoor clip") {
  config.opt_clip = true
}
parser.on("-r", "backup libedoor reader") {
  config.opt_reader = true
}

begin
  parser.parse!
  x = LiveDoor.new(config)
  x.login
  x.save
rescue OptionParser::ParseError => err
  $stderr.puts err.message
  $stderr.puts parser.help
  exit 1
end