Pythonでmixiのプロフィール画像を変更する
あけましておめでとうございます。
早起きしてPython書き初めしたのでご報告です。
今年はmixiのプロフィール画像を日ごとに変更したいと思った。mixiはプロフィール用画像を複数設定できて、その中から一枚をメインの画像にする。APIとか分からないので mechanize でやれば良いやって思ったのだけど、やってみたら少しハマったのでメモ。
とりあえず成果物
https://gist.github.com/1545546
使い方
- メールアドレスとパスワードを使ってログイン。
- プロフィール画像の一覧から現在のプロフィール画像を削除(しなくても良い)
- 新しいプロフィール画像を追加(level="1"は友人向け、"2"は全体向け)
- 画像はjpegのみ(mixiの仕様)
print "login" m = MixiProfileImage( EMAIL_ADDRESS, PASSWORD ) print "delete current profile image" images = m.filter(level="1") for k, v in images.iteritems(): m.delete(v) print "add new profile image" image = m.add( FILE_PATH , level="1", is_main="y")
他には 公開範囲、メイン画像どうかの 変更 と 絞り込み ができる。
mechanize なので mixi の仕様が変わったら使えなくなる。
日替わりプロフィールに使える画像たち(参考)
http://www.mcdonalds.co.jp/menu/regular/index.html
http://www.akindo-sushiro.co.jp/menu/item.php
http://www.abysse.co.jp/world/flag/index.html
http://hanshintigers.jp/data/player/2012/index.html#pitcher
同じカテゴリーの画像だと日替わりアイコンにしても混乱させないはず。
仕組み
mechanizeで操作している。
画像の追加はファイルをPOSTで送信するだけなので簡単。
# self.client = mechanize.Browser() self.client.select_form(nr=0) self.client["level"] = [level] self.client.add_file(open(path), "image/jpeg", path) self.client.set_all_readonly(False) self.client.submit()
画像の削除でハマった。
実際にブラウザで操作すると分かるのだけど、マウスでの操作が何段階かある。それらはJavaScriptで制御されていて最終的にajaxでリクエストを投げている(動きから判断した)。なので、mechanizeでその操作をそっくりなぞってみようとしたら、mechanizeはJavaScriptの動作は再現されない。そこで最終的に投げられるajaxのリクエストを調べて真似た。
以下やったこと
- chrome developer tools を開く(Control+Alt+i)
使い方はこの記事が参考になる
Google ChromeのJavaScriptデバッガの進化がすごい - 0xFF
http://d.hatena.ne.jp/os0x/20110422/1303468821
- Scriptsタグの XHR Breakpoints の Any XHR のチェックを ON
- 画像削除の一連の動作を普通にマウスでする
- protorype-effects-なんとかファイルの途中でブレーク
- ソースの下部にある{}をクリックすると、933行目で止まっている
this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); if (this.options.asynchronous) { this.respondToReadyState.bind(this).defer(1) } this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); this.body = this.method == "post" ? (this.options.postBody || D) : null; this.transport.send(this.body); // <- break
- 上記ソース1行目の this.url に 最終行 this.body を POST で送信しているのが分かる
- this.url には secret っていうキーみたいなのがある
- とりあえず普通にHTMLソースを調べると secret っぽいキーがあったのでそれを利用する
RPC_URL = "/system/rpc.json?auth_type=postkey&secret=%s" % secret params = '{"jsonrpc": "2.0", "method": "jp.mixi.profileimage.deleteEntry", "params": {"image_name": "%s"}, "id": 0}' % image_name self.client.open(url, params)
- できた!!!