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

雀巽の日記帳

雀巽が綴る日常の記録

ブログを移行しました

FC2ブログからはてなブログ

本日、FC2からはてなへブログを完全移行しました。
本記事以前の記事は全てFC2から移行したものとなります。

移行にかなり手こずったので移行手順をまとめてみました。 以下のような構成になっています。

2の画像の移行ですが、このサイトのように画像を別の場所にアップロードする方法はありましたが、はてなフォトライフへの移行方法はいくら探しても見つかりませんでした。そのため、オリジナルな方法で強引に対応しています。

良い移行方法をご存知の方がおりましたら教えていただけると嬉しいです!

移行手順 其の壱(記事)

作業にあたっては、以下のサイトを参考にしました。

作業フロー

  1. FC2からデータをエクスポート
  2. エクスポートしたデータを加工
  3. はてなブログへインポート

とても単純な流れですね!でもこれだけだと、画像データ自体は移行されません。 現時点ではどうしたらいいのかさっぱりわからないので、とりあえず後回し。

FC2からデータをエクスポート

FC2ブログの管理画面(FC2ブログのURLに"?admin"を付与)へログインし、以下の通り操作します。書き方荒すぎるけど気にしない気にしない。

[ツール] -> [データバックアップ]
[エクスポート] -> [全ての記事] -> [ダウンロード]

これで、[UserName].txtが落とせます。
私の場合necojackarc.txtという名前でした。 ここに記事が全部入ってる!

Movable Typeというフォーマットで落ちてきます。
以下、Movable TypeとかMTファイルとか呼ぶと思います。

エクスポートしたデータを加工

テキストファイル編集ってことでVimの出番登場。
MacVimで先ほどダウンロードしたファイルを開きます。
好きなテキストエディタを使いましょう!!

まずは文字コードと改行コードを確認。:set fenc?で確認したところ、utf-8と出ました。ちなみに改行コードを:set ff?で調べたところunixになってました。つまりLFですね。

Macで作業している分には、恐らくこのままで問題ありません。

次は、Movable Typeメタデータ・セクションをいくつか編集します。各項目の詳細についてはここに書いてありました。

CONVERT BREAKS
CONVERT BREAKS: defaultになっていたので、CONVERT BREAKS: 1に全て置換します。念のため、他の値だったとしても拾えるように以下の通り置換。泥臭い書き方してます。

:%s/CONVERT BREAKS:.*/CONVERT BREAKS: 1/gc

SECRET および PASS
FC2ブログのコメント欄独自のメタデータな気がします。消し去りましょう。ただし、SECRET: 1は管理者のみが閲覧可能な非表示コメントですので、その場合はコメントを消すなど対応したほうが良いかもしれません。私の場合はなかったので、単純に全て消し去りました。

:%s/SECRET:.*//gc
:%s/PASS:.*//gc

はてなブログへインポート

いよいよインポートします!

[ダッシュボート] -> [インポート] -> [Movable Type形式]  
[ファイルを選択] -> [文字コード選択へ進む]  
[utf-8] -> [インポートする]

インポート完了!ブログを確認!
……はい、うまく行かない!なんでやねん!

以下、2つがダメでした。

  1. 改行箇所が全て<p>タグで囲まれてしまいキモい
  2. コメントが存在する記事で改行が無視されていてヤバイ

要は改行関係がアウトです。
1ははてなの改行処理の仕様っぽいですが、2は謎です。

ざっと眺めたところ、BODY:から-----までに存在する改行を<br>に変換すれば全て解決する気がする。とっても力技。

とりあえず試してみる。まず変換。
Ruby初心者がRubyで頑張ってみた。

filename = ARGV[0]

File.open(filename) do |input|
  File.open("formatted_" + filename, "w") do |output|
    flag = false

    input.each_line do |line|
      if flag && (line.chomp == "-----") then
        flag = false
        output.puts "" # 改行を挿入
      end

      if !flag then
        puts line
        output.puts line
      end

      # BODY: -> -----
      if flag then
        puts line + "<br>"
        output.write line.chomp + "<br>" # 改行 -> <br>
      end

      if line.chomp == "BODY:" then
        flag = true
      end

    end
  end
end

以下の通り実行。

$ ruby ./formatMTFile.rb necojackarc.txt

生成されたformatted_necojackarc.txtをはてなブログへインポートし確認……できた!できました!!

未解決の問題あり

一見すると無事にブログ移行は完了しました。
しかし、未解決の問題があります。

それは、画像の移行をしていないこと!

今現在はFC2にアップロードされてる画像を参照しに行っています。このままでも問題が起きないとは思うけど、完全移行とは言い難い状態……。

というわけで、色々頑張ってみました。

移行手順 其の弐(画像)

どうすれば移行できるかなと色々考えた結果、シンプルに次の手順で突き進んでみることにしました。

  1. FC2の全画像をダウンロード
  2. はてなフォトライフへアップロード
  3. MTファイル内のURLを置換

この手順での最大の障壁となるのは、

アップロード前後のファイル名をマッピングすること

かと思います。

はてなフォトライフへ画像をアップロードすると、元のファイル名とは何の関係もない名前で保存されてしまいます。 そのため、上記のマッピングが大きな課題となります。 もしかしたら設定方法があるのかもしれませんが、私には見つけることができませんでした。

FC2の全画像をダウンロード

意外と簡単にできました。FC2の管理画面で以下の操作をすればOKです。

[ツール] -> [データバックアップ]
[ファイルバックアップ] -> [画像ファイル] -> [リストを開く]

開いたページをWebページ、完全で保存します。 100件以上ある場合は複数に分かれていそうなので注意。

保存し終わったら画像を1つのディレクトリにまとめてしまいます。

はてなフォトライフへアップロード

最大の障壁がきました。一番の難所です。勘ですが、はてなフォトライフAPIを使って画像を投稿すれば、投稿前のファイル名と投稿後のURLが取得できそうな気がします。

おしえてGoogle先生

……!ありました!以下の記事で、はてなフォトライフAPIを使って画像を投稿し、なおかつ投稿後のURLを表示したりするスクリプトが公開されています!

はてなフォトライフにアップロードするスクリプト

大感謝です。以下、ありがたくスクリプトを改造させていただきます。
ファイルを作成、実行権限を付与、コピーアンドペースト。そして大感謝。
はてなブログのusernameとapi_keyの設定も忘れずに。

こういった引用や改造の際の正しいルールに自信がないため、 おかしなところがあったらご指摘いただけると嬉しいです。 急いで直します。

まずは、スクリプトを実行できる環境を整える必要があります。
以下をターミナル上で実行したら動くようになりました。

$ brew update
$ brew install ImageMagick
$ gem install wsse

次にスクリプトを改造します。必要な機能は以下。

  • アップロード先のフォルダを指定すること
  • 元のファイル名とアップロード後のURLの組を出力すること

こうなりました。

#!/usr/bin/env ruby -Ku
require 'rubygems'
require 'net/http'
require 'wsse'
require 'base64'
require 'digest/sha1'
require 'date'
require 'pp'
require 'optparse'

$show_img_url = 0
opt = OptionParser.new
opt.on("-u","--url"){ $show_img_url = 1 }
opt.on("-s","--src"){ $show_img_url = 2 }
opt.on("-m","--migrate"){ $show_img_url = 3 }
opt.parse!(ARGV)

if ARGV.size < 1 or not ARGV.all?{|e|  File.exist? e} then
  puts "usage: #{__FILE__} 画像ファイル名
          ファイル名はタイトルになる。
          タイトル指定したいときはファイル名を使えば良い。
        -u (--url) で <img> タグ
        -s (--src) で src url
        -m (--migrate) で filename, src url"
          exit 2
end

ARGV.each{|e|
    f_name = e
    tmp_name = ""
    #ファイル名をタイトルに採用
    a = File.basename(f_name).split('.');
    file_name = a.join('.')
    a.pop
    title = a.join('.')

    #png だったらjpg にして送信(fotolifeは容量制限がきついのでPNGよりJPEGにする)
    if ( File.extname(e) =~ /png/i) then
        tmp_name = e+"_fotolife_tmp_"+Time.now.to_i.to_s + ".jpg"
        `convert \"#{f_name}\"  \"#{tmp_name}\"`
        f_name = tmp_name
    end

    #写真の jpg は向きを修正する
    if ( File.extname(e) =~ /jpe?g/i && !`which orientation_fix `.empty?) then
        tmp_name =  "#{title}_orientation_fixed_"+Time.now.to_i.to_s+".jpg"
        `cp '#{f_name}' '#{tmp_name}' `
        `$(which orientation_fix)  #{tmp_name} `
        f_name = tmp_name
    end

    #写真のサイズを適宜修正する
    if (width = `identify -format %w #{f_name}`.strip.to_i) > 1200
        `mogrify -resize 1200 #{f_name} `
    end

   #main
    content = Base64.encode64(open(f_name).read)
    xml = "<?xml><entry xmlns=\"http://purl.org/atom/ns#\" >"+
            "<title>#{title}</title>"+
            "<content mode='base64'  type='image/jpeg'>#{content}</content>"+
            "<dc:subject>FC2 Imported</dc:subject>"+
            "</entry>"
    username, api_key = %w!USERNAME API_KEY! # TODO: 要設定

    http = Net::HTTP.start("f.hatena.ne.jp", 80)
    #response = http.post('/atom',xml, {'X-WSSE' => WSSE::header(username,api_key)})
    response = http.post('/atom/post',xml, {'X-WSSE' => WSSE::header(username,api_key)})
    response.body =~ /<hatena:syntax>([^<]+)<\/hatena:syntax>/
    foto_id = $1
    puts "[#{foto_id}#{':w600' if width>1200}](#{title})" unless $show_img_url > 0
    if $show_img_url > 0 then
      user = foto_id.split(/:/)[2]
      f_id = foto_id.split(/:/)[3].gsub /j/, ""
      src = "http://cdn-ak.f.st-hatena.com/images/fotolife/t/#{user}/#{f_id[0,8]}/#{f_id}.jpg"
      puts "<img src='#{src}' />" if $show_img_url == 1
      puts src if $show_img_url == 2
      puts file_name + "," + src if $show_img_url == 3
    end

    File.unlink tmp_name if File.exists? tmp_name
    File.unlink f_name   if File.exists?(f_name) && (f_name != e)

}

改造後は-mをつけて実行すれば、ファイル名,アップロード後のURLと出力されます。また、アップロード先はFC2 Importedとしています。

抽出した画像に対して以下を実行してアップロード完了!そしてマッピング情報もゲット!

$ fotolife * -m > mapping.txt

MTファイル内のURLを置換

確認してみたところ、FC2での私の画像ファイルは全て http://blog-imgs-<数値>.fc2.com/n/e/c/necojackarc/<ファイル名> に格納されていました。

上記とmapping.txtを元に、MTファイル内の画像ファイルのURLを置換するプログラムを作成します。もはやRubyの練習状態。

mtFile = ARGV[0]
mappingFile = ARGV[1]

patternHeader = 'http:\/\/blog-imgs-\d*\.fc2\.com\/n\/e\/c\/necojackarc\/'

File.open(mtFile) do |input|
  all = input.read

  File.open(mappingFile) do |mapping|
    mapping.each_line do |line|
      str = line.chomp.split(',')
      pattern = patternHeader + str[0]
      all.gsub!(/#{pattern}/, str[1])
    end
  end

  File.open("replaced_" + mtFile, "w") do |output|
    puts all
    output.write(all)
  end
end

そして、以下の通り実行します。

$ ruby ./replaceImages.rb formatted_necojackarc.txt mapping.txt

すると、replaced_formatted_necojackarc.txtという長ったらしいファイルが生成されます。もう少しファイル名考えたほうが良かったかな……。

このファイルをはてなブログへインポートすれば完全移行完了です!

長かった……本当に長かった……思ったよりはるかに時間がかかったよ……。 まだまだ未熟者なため、ブログ移行に一晩かかってしまいました。 精進するしかない!

まとめ

最後に全体の手順を簡単にサクッとまとめなおし。

  1. FC2からデータを全てエクスポート
  2. メタデータ・セクションを編集
  3. BODY内の改行を<br>に変換
  4. 画像をはてなフォトライフへアップロード
  5. 画像のリンク先をFC2からはてなへ変更
  6. はてなブログへインポート

これにてFC2からはてなへの移行終了です。
はてなブログ生活開始ですね!使いこなせるかなー!笑

そろそろ流石に寝なくては!おやすみなさい!