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

cloverrose's blog

Python, Machine learning, Emacs, CI/CD, Webアプリなど

flickrapiを使って画像をUploadしてみた

PythonFlickrライブラリであるflickrapi(Python Flickr API kit - Stüvel photography)を使って画像のアップロードと、アップロードした画像のオリジナルURLの取得ができるようになったのでメモ。

インストール

pip install flickrapi

アプリの作成

http://www.flickr.com/services/api/keys/Flickrのアプリを作る(Twitter Developerページでアプリを作る感じ)。
作るとKEYとSECRETが手に入る。

ユーザー認証

画像をアップロードしたいのは基本的にゆゆ式アイコン用のユーザーだけなので認証はPython FlickrAPIにあるように以下のスクリプトを実行すればいい。

import flickrapi

api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
api_secret = 'YYYYYYYYYYYYYYYY'

flickr = flickrapi.FlickrAPI(api_key, api_secret)

(token, frob) = flickr.get_token_part_one(perms='write')
if not token:
    raw_input("Press ENTER after you authorized this program")
flickr.get_token_part_two((token, frob))

実行すると、ブラウザが開くのでアプリを認証ボタンを押せばいい。

認証すると~/.flickr以下に認証データがキャッシュされるので、以降は認証を実行しても実際はキャッシュの情報が使われる。


画像のアップロードと画像のオリジナルURLの取得

画像アップロードが成功すると、photo_idが取得できる、それを使って画像のオリジナルURLを作る。

Flickrの画像URLの形式はFlickr Servicesにある。

import flickrapi
api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
api_secret = 'YYYYYYYYYYYYYYYY'


def make_api():
    api = flickrapi.FlickrAPI(api_key, api_secret)
    (token, frob) = api.get_token_part_one(perms='write')
    if not token:
        raw_input("Press ENTER after you authorized this program")
    api.get_token_part_two((token, frob))
    return api


def upload(api, filename):
    return api.upload(filename).find('photoid').text


def get_original_url(api, photo_id):
    fmt = 'http://farm{0}.staticflickr.com/{1}/{2}_{3}_o.{4}'
    photo = api.photos_getInfo(photo_id=photo_id).find('photo')
    return fmt.format(photo.get('farm'), photo.get('server'), photo.get('id'), photo.get('originalsecret'), photo.get('originalformat'))


def upload_and_save_url(filename):
    api = make_api()
    photo_id = upload(api, filename)
    url = get_original_url(api, photo_id)
    print url

注意点

uploadの引数のfilenameにはUTF-8エンコードされた文字列(str)を使うこと!Unicode文字列を使うと、POSTリクエストを作成するときに、画像データ(バイナリ文字列)をUnicodeにデコードしようとしてUnicodeDecodeErrorが発生してしまう。

原因がずっとわからなくてかなり時間取られてしまった。PythonのUnicodeDecodeError、UnicodeEncodeErrorを正しく理解する - Sticker@Somethingの「Pythonの暗黙的な文字列型変換について」を読んでやっと気づくことができた。

おまけ

経緯

ゆゆ式アイコンではTwitterの画像サーバーからオリジナルサイズの画像をクライアント側で正方形にしていた。
アイコン数が増えてきてクライアントの負荷が増大した。
そこで、サーバー側で必要サイズ(140px×140px)の正方形にした画像を用意することにした。
しかし、自宅サーバーでは画像を捌き切れない。

そこで、外部のサービスに画像をアップロードすることにした。

画像アップロードサービスとして思いついたのは、
Flickr Twitter Tumblrなどがあった。
この中でFlickrを選んだ理由は、Organize機能によって画像の全消去とかが簡単にできるから。例えば今は140px×140pxだけど将来サイズを変えた時に昔の画像は消して新しい画像に交換するとかが簡単そうだなとおもった。
また、オリジナル画像をきちんと保存してくれているのも大きい。

ライブラリ調査

こういった経緯でFlickrに画像をアップロードするライブラリを調査した。
Flickr ServicesPythonの項目をみると

  1. Beej's Python Flickr API Python Flickr API kit - Stüvel photography
  2. flickr.py flickrpy - A Python library for the Flickr API. - Google Project Hosting
  3. python-flickr-api python-flickr-api - Python implementation of Flickr - Google Project Hosting, alexis-mignon/python-flickr-api · GitHub

の3つがみつかった。

ドキュメントの充実度・認証の簡単さからBeej's Python Flickr API(Python Flickr API kit - Stüvel photography)を選んだ。