はてなダイアリーの日記データを hatena-mode 用のファイルに変換する

はてなダイアリーのエントリを hatena-mode 用に全部ローカルに持ってこようと思ったんだけど、hatena-mode の hatena-get-webdiary はなんか自分の環境だとうまく機能しないので、Ruby でやることにした。
はてなダイアリーのエクスポートは

  • はてダの「管理 > データの管理 > 日記のエクスポート」からか
  • または「http://d.hatena.ne.jp/[userid]/export」からできる。

hatena-diary-export2hatena-mode-files.rb

名前ながっ!
でもってネーミングセンスがよろしくない…。
だけど本質はそこじゃないので大丈夫。ちゃんと使えます。
もしこのスクリプトを使う場合は

  • 以下のスクリプトを「EUC」で保存してください。
  • hatena-mode 用のディレクトリ (~/.hatena) にこのスクリプトとエクスポートしたファイル ([userid].xml) を置いて下さい。
  • 実行方法は「$ ruby hatena-diary-export2hatena-mode-files.rb [userid]」です。
  • あとはちょっと待ってればすぐに終わると思います。
  • 存在しない日記ファイルだけが追加されます。文字コードは「EUC」です。
    • EUC じゃやだってときは、下の方にある「toeuc」を「tosjis」や「toutf8」に書き換える
#!/usr/local/bin/ruby -Ke
require 'kconv'
require 'open-uri'
require 'rexml/document'

userid = ARGV[0] || "gan2"
export_url = "http://d.hatena.ne.jp/#{userid}/export"
filename = "#{userid}.xml"
exists = {}

Dir.open("./") do |d|
  d.each do |f|
    exists[f] = true if /20\d{6}/ =~ f
  end
end

#open(export_url) do |f|
open(filename) do |f|
  doc = REXML::Document.new(f)
  doc.root.each_element do |e|
    date = e.attributes['date']
    body = e.elements['body'].text.toeuc.lstrip.chomp
    date.gsub!('-', '')
    unless (exists[date])
      open(date, 'w') do |f|
        f.write(body)
      end
    end
  end
end

OpenURI を使ってローカルにエクスポートしなくてもいいようにしたかったんだけどなんか REXML がパースに失敗するし、この処理は別に何度もやるようなものでもないと思ったので、別にいいかってことにした。


今回日記をローカルに持ってきた理由は、バックアップを手元に残しておきたかっていうのもそうなんだけど、それよりもずっと大きな理由がある。
それは、過去の日記を検索するときに、Web 上で検索をかけるよりも、ローカルで moccur-grep-find をした方が便利なことに気付いたからで、そのためには手元に日記のデータが必要だったからだ。
そんなわけで、hatena-mode 使ってる人はローカルに日記データを持ってきて、moccur-grep-find で .hatena 以下を検索してみるといいですよ!

今回勉強になったこと

  • shebang の -K オプションと、スクリプト中の $KCODE の違い
  • REXML で String が欲しい場合は get_text じゃなくて text を使う。
    • get_text で返ってくるのは REXML::Text オブジェクトなので、Kconv の toeuc とかが使えないので注意。
  • String#strip と String#lstrip.chomp は同じかと思ったら微妙に違う。
    • あとで検証したい。
  • デバッグしてるときに間違ったファイル名のファイルをたくさん作っちゃったりしたんだけど、そのときに dired の「% d」(正規表現にマッチしたファイルを d でマークする機能) が役に立った。今まであまり使う機会がなかったけど、はっと思い出して使ってみた。