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

YAMAGUCHI::weblog

土足で窓から失礼いたします。今日からあなたの息子になります。 当年とって92歳、下町の発明王、エジソンです。

mixiダイアリーのバックアップ用スクリプトを書いてみた

Python

動機

ある日突然外国の方から「君が作ったmixi APIを使ってみたら、うまく動かないんだけど。」っていわれました。どうも奥さんが日本人でmixiダイアリーのバックアップを取りたいらしい。が、そもそも俺がPythonで書いたmixi APImixiツールバーのものが基本で、mixiツールバー自身はそんな機能を持ってないので「無理だよ」と言ったら、「とても残念だ」という返事が返ってきました。
それで突っぱねておしまいに出来たんだけど、なんかかわいそうだからバックアップできないかなあと思って実装してみました。

使った物

概要
  1. mixiへログイン
  2. 各月ごとのmixiダイアリーの各エントリのURL取得
  3. 各エントリのタイトル、タイムスタンプ、内容、コメント(ユーザ名、タイムスタンプ、内容)を取得
  4. ファイルへの吐き出し(オプション的な)
mixiへのログイン

まずmixiにログインしないとそもそもmixiダイアリーを参照できないので、ログインします。その部分については西尾さんのエントリをそのまま使わせてもらいました。(西尾さんありがとうございます)

各エントリのURL取得

mixiダイアリーの各月のエントリ一覧はYEAR年MONTH月の場合

http://mixi.jp/list_diary.pl?year=YEAR&month=MONTH

で取得できます。この中で各エントリへのリンクである

http://mixi.jp/view_diary.pl?id=XXXXXXXX&owner_id=XXXXXXX

となっているURLを取得します。このときページ内の他のURLを持ってこないように

view_url_r = re.compile('^view_diary.pl\?id=[0-9]+&owner_id=[0-9]+$')
if url.match(u):
    urllist.append(url)

みたいな感じでURLを絞ってます。(コード参照)

各エントリの内容取得

最初はHTMLParserを使ってたんですが、JavaScriptコード内のタグのスニペットを実際のタグと誤認識してバグる&フィルタをかけるのがめんどくさかったんでlxmlを使うことにしました。

lxmlはXPathが分かればものすごく簡単で、かつとても速いのでかなり気に入りました。使い方は

tree = etree.parse(StringIO(data), etree.HTMLParser())
data = tree.xpath('//div[@class="hoge"]//a/@href')
data2 = tree.xpath('//div[@class="piyo"]//p/text()')

みたいな感じで使えます。とりあえず絶対パス相対パスにさえ気をつけておけばさくっとほしいデータを取得できるはずです。先頭で'//'を使うとどんなノードを渡しても必ずルートノードから参照してしまうので、'.//'とピリオドを忘れないように。(コード参照)

ファイルへの吐き出し

あとは取得した物を適当にファイルにはき出すだけです。今回はファイルにはき出す部分はあくまでサンプルとして実装してみました。実際はMixiExtractorクラスさえあればgetMonthEntryBodyメソッドの返り値を利用していかようにも書けると思います。
なお、getMonthEntryBodyメソッドは

- date (日記のタイムスタンプ)
- title (日記のタイトル)
- body (日記の本文)
- comments (コメント)
    - cdate (コメントされたタイムスタンプ)
    - cuser (コメントを書いたユーザ名)
    - cbody (コメントの内容)

のリストな感じでデータを返してきます。commentsもリストです。

使い方
$ python mixi_downloader.py -u USERNAME -p PASSWORD [-c]

USERNAMEは登録しているメールアドレス、PASSWORDはパスワードです。また-cオプションはコメントの取得の有無を表しています。つけなければコメントは取得しません。

注意

mixi内のページをスクレイピングしているため、あまり高頻度でアクセスすると一時アカウント停止状態にさせられてしまいます。
f:id:ymotongpoo:20090207013326p:image

その後

メールをくれた外国人に「こんなんできたよ」と返信したらとても喜んでくれました。

My wife looked pretty happy about it, so thanks again.

こういうメールをもらうと自分の趣味でやってたことで喜んでくれる人がいるんだなあと思ってうれしくなります。面白い時代に生きているなあと改めて実感します。