Flickr 一括アップローダ

はじめに

10日間ほど台湾一周の旅に出てまして、林家夫妻のようにスナップ写真を大量に撮ってきたんですよ。


んで Flickr への写真アップロードは、iPhotoプラグイン(FFXporter)を使用していたけど、1000枚くらいをアップしようとすると、一枚一枚チマチマと処理するので、どうにも時間がかかってイライラしちゃう。もっとこうドワッと一気にやってもらいたいのです。


Flickr API を使って自分でスクリプト書いてる人が山ほどいらっしゃるようなので、自分も半分趣味で作ってみる。というか参考URLのツギハギだけど。

Flickr API 操作の Python ライブラリをインストール

Python 用ライブラリはいくつかあるみたいだけど、どれがイイんでしょうね。ここでは一番最初に目についた Stüvel.eu のを使ってみてます。


easy_install で Python Flickr API をインストール。

$ easy_install flickrapi

Flickr API Key の取得

Apply for a new API Key から Flickr API 利用に必要な API Key を取得。

実装

あ、ちなみになぜか Python2.5 環境で書いちゃいました。


flickr_uploader.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from __future__ import with_statement
import sys
import os
import threading
import time
import re
import flickrapi

API_KEY = '自分のAPI Key'
API_SECRET = '自分のAPI Secret'

PAT_EXT = re.compile(r'\.(jpg|jpeg|avi)', re.I)
pict_dir = '.'

class UploadWorker(threading.Thread):
    """
    """
    def __init__(self, flickr, files, lock, name=None, args=(), kwargs={}):
        """コンストラクタ"""
        super(UploadWorker, self).__init__()
        self.flickr = flickr
        self.files = files
        self.lock = lock

    def _pop_file(self):
        """
        """
        with self.lock:
            try:
                f = self.files.pop()
            except IndexError:
                f = None
        return f
        
    def run(self):
        """
        """
        while True:
            f = self._pop_file()
            if f is None:
                break
            
            print "[%s] Upload start: %s" % (self.getName(), f)
            try:
                self.flickr.upload(os.path.join(pict_dir, f), is_public=0, is_family=1, is_friend=1)
            except:
                print "[%s] Failed... Skip" % self.getName()
            else:
                print "[%s] OK: %s" % (self.getName(), f)


def init_flickr():
    """Initialize and authenticate FlickrAPI"""
    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))
    return flickr

def main():
    """
    """
    # 画像ディレクトリ設定
    global pict_dir
    if len(sys.argv) > 1:
        pict_dir = sys.argv[1]
    
    # 画像ファイル名取得
    files = [f for f in os.listdir(pict_dir) if not f.startswith('.') and PAT_EXT.search(f)]
    if len(files) == 0:
        print "No files in the directory."
        sys.exit()
    print "File num: %s" % len(files)
    
    # Flickr API 初期化 & 認証
    flickr = init_flickr()
    
    # アップロード
    lock = threading.Lock()
    workers = []
    for i in xrange(5):
        w = UploadWorker(flickr, files, lock)
        workers.append(w)
        w.start()
    
    # 処理終了待ち
    for w in workers:
        w.join()
    print 'Done.'

def _test():
    import doctest
    doctest.testmod()

if __name__ == '__main__':
    main()

これでとりあえず自分の欲望は解消できましたよ。

$ python flickr_uploader.py /path/to/pict_dir/


突っ込みや改善案があれば是非。