How about your tumblr blog?

tumblrブログの移行どうしようかと色々探してみたら、APIで全ての記事を取得できた。とりあえず手作業でできる程度の量であればこの方法が一番早いんじゃないかと思う。一括して実行するツールは次回のエントリーに書こうと思う。

tumblr API v1

tumblr APIは現在v1v2がある。v2はAPI tokenが必要だったので、古い方のv1を使ってxmlを取得するようにした。しかも手作業だwww

v1 APIでは、一回あたり最大50件の記事を取得できる。僕の場合は342件だったので、350/50 = 7回取得すれば全ての記事が取得可能だ。postsタグのtotal属性に記事数が書いてある。

tumblr.xml
..<posts start="0" total="342">..

全部のxmlからpostタグを抜き出して1ファイルにtumblr.xmlとしてまとめておく。それからこんなコードを書いてみた。これを実行すると_postsディレクトリ以下に、post id毎にコンテンツ部分のhtmlとOctopressで必要なメタデータとなるmarkdownファイルを出力できる。

tumblr2markdown.phplink
<?php
$file = './tumblr.xml';
$xml = simplexml_load_file($file);
$posts = $xml->posts;
$root = "./_posts";
if (!is_dir($root)) {
mkdir($root);
}
foreach ($posts->post as $post) {
$id = (string)$post['id'];
$url = (string)$post['url-with-slug'];
$date = (string)$post['date'];
$slug = (string)$post['slug'];
$dt = new \DateTime($date);
$tag = array();
if (isset($post->tag)) {
foreach ($post->tag as $t) {
$tag[] = "$t";
}
}
$titleVar = "regular-title";
$title = isset($post->$titleVar) ? $post->$titleVar : null;
$title = "$title";
$bodyVar = "regular-body";
$body = isset($post->$bodyVar) ? $post->$bodyVar : null;
$body = "$body";
$dir = $root . "/$id";
if (!is_dir($dir)) {
mkdir($dir);
}
$metaFile = sprintf("%s-%s.markdown", $dt->format('Y-m-d'), $slug);
$meta = array(
'---',
'layout: post',
sprintf('title: "%s"', $title),
sprintf('date: %s', $dt->format('Y-m-d H:i')),
'comments: false',
sprintf('categories: [%s]', implode(', ', array_map(function($t){ return sprintf("'%s'", $t);}, $tag))),
'---',
);
file_put_contents($dir . "/" . $metaFile, implode("\n", $meta) . "\n");
$bodyFile = "body.html";
file_put_contents($dir . "/" . $bodyFile, $body);
}

htmlからmarkdown形式に変換するのはpandocというツールが優秀だった。html2textというツールもあったが、見事に文字化けした上に、期待したmarkdownにならなかった。brew installできるのは良かったんだけどね。

pandocはこんなオプションをつけて実行する。

pandoc
pandoc -f html -t markdown body.html -o body.md

あとはシェルスクリプトを書いてbody.mdを2013-01-01-your-post-slug.markdownの後ろに追記すればいい。拡張子がmdとmarkdownで違うのはシェルスクリプトでファイル名の正規表現を書いてごにょごにょするのがめんどくさかったからだ。完全に手抜きだ。言い訳はしない。

pandoc.shlink
#!/bin/sh
cmd_pandoc="pandoc -f html -t markdown body.html -o body.md"
posts=`ls _posts`
root_dir=`pwd`
for post in ${posts}
do
post_dir="_posts/${post}"
echo ${post_dir}
# html 2 markdown
cd ${post_dir}
${cmd_pandoc}
rm body.html
markdown=`ls *.markdown`
for md in ${markdown}
do
echo "" >> ${md}
cat body.md >> ${md}
rm body.md
done
# done post
cd ${root_dir}
done

Conclustion: Done! but it's slightly troublesome.

tumblrから自分の記事をxmlで取得して、pandocを使ってmarkdownに変換する方法を書いた。しかし、若干手作業が多い。xml取得からmarkdown変換までを一気にやるツールについては次回のエントリーに書きたいと思う。