テキストファイルをはてなダイアリーにインポート。
MacBookのハードディスクが壊れて数ヶ月分の日記が手の届かないところに行ってしまった。
失ってしまったものをいつまで思ってもどうしようもない。前に進まないといけない。今後、こういうことを無くすためにはてなのサブアカウントを利用してはてなダイアリーに書くことにした。
まずは生き残っているファイルをインポートするために必要なファイルを作成する処理をRubyで書くことに。実装する上での要件はこんな感じ。
- 日記は1日1ファイル
- ファイル名はyyyy-mm-dd.txtが基本
- 場合によっては曜日が入る
- テキストファイル
- 年→月でディレクトリが作られている
- はてなダイアリーにインポートするためのファイル形式はXML
<?xml version="1.0" encoding="UTF-8"?> <diary> <day date="2006-04-08" title=""> <body> 本文 </body> </day> </diary>
というわけで、久しぶりのRubyを楽しみつつサクサクと書く。
途中、REXMLの使い方がわからなかったのでこちらを参考にさせてもらい完成。
さぁ、れっつインポート、したけど読み込まれない。
何故にと思いあれやこれやと出力されたファイルをいじってインポートさせ動作を確認。どうやらAttributeの値を''ではなく""で囲んでやらないと読み込んでくれないようだと判明。
REXMLでどうやって''を""にすればいいのだ、面倒だし複雑なフォーマットではないので、ベタに文字列として出力してやろうかと思ったけど、それはちょっと格好悪いとゴーストが囁くので、Google様にお尋ねしたところ、バッチリな回答がこちらにあったので、コピペして実行、インポートをしたところ無事に読み込まれた。
完成したスクリプトはこんな感じ。
require 'kconv' require 'rexml/document' $kcode = 'u' def list_diary(dirname) return unless FileTest.exist?(dirname) or FileTest.directory?(dirname) Dir.foreach(dirname) do |item| next if item == '.' or item == '..' full_path = File.join(dirname, item) if /(^\d{4}-\d{2}-\d{2})(.*)(.txt)/ =~ item body = nil File.open(full_path) do |file| body = file.read end # 重複チェック $diaries.each do |item| if item.has_key?($1) $duplicate << $1 break end end next if $duplicate.include?($1) diary = Hash[$1, body] $diaries << diary else next unless FileTest.directory?(full_path) list_diary(full_path) end end end if ARGV.size < 1 or not FileTest.directory?(ARGV[0]) $stderr.puts("ディレクトリを指定しろ。".tosjis) exit end $diaries = [] # 日記を格納 $duplicate = [] # 重複している日を格納 # テキストファイルを読み込み配列に格納 list_diary(ARGV[0].chomp) # 日付が重複していたら該当の日付を出力して処理を終了 unless $duplicate.empty? $duplicate.each {|item| puts item} exit end # XMLファイル作成 # attributeの値が''で囲まれてしまうとうまく取り込めないようなので # ""で囲むように設定 REXML::Attribute.class_eval( %q^ def to_string %Q[#@expanded_name="#{to_s().gsub(/"/, '"')}"] end ^ ) entries = REXML::Element.new("diary") $diaries.each do |diary| day = REXML::Element.new("day") diary.each do |date, body| day.add_attribute("date", date.toutf8) day.add_attribute("title") day.add_element("body").add_text(body.toutf8) end entries.add_element(day) end File.open('import.xml', 'w') do |file| file.puts(REXML::XMLDecl.new("1.0", "UTF-8")) file.puts(entries) end