FutureInsight.info

AI、ビッグデータ、ライフサイエンス、テクノロジービッグプレイヤーの動向、これからの働き方などの「未来」に注目して考察するブログです。

Flickrからアルバムを生成するPythonコード

以前、公開したPythonのソースコードが意外に好評だったので、このURLのアルバムのHTMLを出力しているPythonコードをさらします。

少々長いので、続きは以下の「続きを読む」で。Pythonに興味がない人にはおもしろくないので、スキップしてください。


まず、htmlを生成しているので、テンプレートエンジンを使っています。テンプレートエンジンは枯れていてスタンダードの感のあるCheetahです。

あと、simplejsonも使っています。

両方ともeasy_installを使って以下のようにインストールすると簡単です。

%easy_install simplejson
%easy_install Cheetah

で、この生成ツールなのですが、以下の構成からなります。sqliteはPython2.5より標準でサポートされるようになりました。これはいい感じなので、がんがん使いましょう。

  • flickr.py : Flickrからデータを取得し、sqliteでデータベースに格納。そのデータベースからテンプレートエンジンを使ってhtmlを生成。
  • album.tmpl : 上のスクリプトで使うテンプレートの定義。

下のエントリーで記載したような形式のCSVファイルを引数に指定して利用します。

コマンドラインは以下の通りです。

%python flickr.py -d file_name #データベースを生成
%python flickr.py -m file_name #上で作成したデータベースからHTMLを出力

最初の行で、大きなデータベースを作っておいて、2つめに渡すファイルはその中で出力するものを限定することも可能です。

以下がflickr.pyのソースコード。

# -*- coding: utf-8; -*-

import sys
import urllib
import time
import simplejson

db_name = "flickr.db"

__doc__ = """
Usage:
#python flickr.py -d file_name : create database from file_name 
#python flickr.py -m file_name : create html from database 
#python flickr.py -h : show this page 
"""

def search_photos( text, page=1, photo_list=[] ):
    args = { 'method'  : 'flickr.photos.search',
             'api_key' : 'ここに自分のAPI_KEYを記入!',             
             'per_page': '500',
             'sort'    : 'date-posted-desc',
             'format'  : 'json',
             'nojsoncallback' : 1,
             'text'    : text,
             'page'    : str(page),
             'extras'  : "date_upload",
        }

    url = "http://api.flickr.com/services/rest/?%s"%(urllib.urlencode(args) )
    time.sleep(1.0)
    flickr_photos = simplejson.loads( urllib.urlopen(url).readline() )
    photo_list = photo_list + flickr_photos["photos"]["photo"]
    if flickr_photos["photos"]["pages"] != flickr_photos["photos"]["page"]:
        return search_photos( text, page+1, photo_list )
    else:
        return photo_list
    
def create_photo_url( photo ):
    template = "http://farm%s.static.flickr.com/%s/%s_%s.jpg"
    return template%(photo["farm"], photo["server"],
                     photo["id"], photo["secret"])

def create_small_photo_url( photo ):
    template = "http://farm%s.static.flickr.com/%s/%s_%s_s.jpg"
    return template%(photo["farm"], photo["server"],
                     photo["id"], photo["secret"])

def create_page_url( photo ):
    template = "http://www.flickr.com/photos/%s/%s"
    return template%(photo["owner"], photo["id"])

def get_query_list( filename ):
    file_obj = open( filename, 'r')
    line_list = file_obj.readlines()
    file_obj.close()
    query_list = []
    for i in line_list:
        if -1 != i.find(","):
            query_list.append( [ n.strip() for n in i.split(",") ] )
    return query_list    

def create_html( query_list ):
    from Cheetah.Template import Template
    import sqlite3
    tmpl = Template(file="album.tmpl")
    conn = sqlite3.connect( db_name )
    all = []
    for i in query_list:
        tmp = {}
        tmp["name"] = i[1]
        photo_list = []
        cur = conn.cursor()
        cur.execute("""
        select photo_url, small_photo_url, page_url, name from photo_table
        where name==\"%s\"
        order by upload_time
        """%(i[1]) )
        for row in cur:
            photo = {}
            photo["photo_url"] = row[0].encode("utf-8")
            photo["small_photo_url"] = row[1].encode("utf-8")
            photo["page_url"] = row[2].encode("utf-8")
            photo["name"] = row[3].encode("utf-8")
            photo_list.append(photo)
        tmp["photos"] = photo_list
        all.append(tmp)
        cur.close()
    tmpl.all_photos = all
    return tmpl

def create_db( query_list ):
    import sqlite3
    conn = sqlite3.connect( db_name )
    try:
        conn.executescript("""
        create table photo_table(
        integer primary key,
        photo_url varchar2(512),
        small_photo_url varchar2(512),
        page_url varchar2(512),
        upload_time integer,    
        name varchar2(512) );
        """)
    except sqlite3.OperationalError:
        print "%s is already exist. if you do not need this file, please remove it."%(db_name)
        sys.exit( -1 )

    cur = conn.cursor()
    for i in query_list:
        photo_list = search_photos( i[0] )
        for j in photo_list:
            cur.execute("""
            insert into photo_table values( %s, \"%s\", \"%s\", \"%s\", %s, \"%s\" )
            """%( hash( create_photo_url( j ) ), create_photo_url( j ),
                  create_small_photo_url( j ), create_page_url( j ),
                  int( j["dateupload"] ), unicode(i[1],'utf-8') ) )
    cur.close()
    cur = conn.cursor()
    try:
        cur.execute("select photo_url, name from photo_table order by upload_time")
    finally:
        cur.close()
    conn.commit()
    conn.close()
        
def main(*argv):
    from getopt import getopt, GetoptError
    try:
        (opts, args) = getopt(argv[1:], 'h:m:d:', ['help', 'html', 'database'])
    except GetoptError:
        print __doc__
        return -1

    for o, a in opts:
        if o in ('-h', '--help'):
            print __doc__
            return 0
        
        if o in ('-m', '--html'):
            query_list = get_query_list( a )
            print create_html(query_list)
            return 0
        
        if o in ('-d', '--datebase'):
            quer_list = get_query_list( a )
            create_db(query_list)
            return 0

if __name__ == '__main__':
    sys.exit(main(*sys.argv))

以下がテンプレートであるalbum.tmplの中身。

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Flickr Photo Album</title>    
<link rel="stylesheet" type="text/css" media="screen" href="http://choichoi.sakura.ne.jp/idols/lightbox.css" />
<link rel="stylesheet" type="text/css" media="screen" href="http://choichoi.sakura.ne.jp/idols/album.css" />
<script type="text/javascript" src="http://choichoi.sakura.ne.jp/idols/lightbox.js"></script>
</head>
<body>
#for $i in $all_photos
	<h2 class="date">$i.name</h2><div class="grid">
	#for $j in $i.photos
		<div class="section fade">
		<a href="$j.photo_url" rel="lightbox"> <span class="shadow">
		<img width="75" height="75" rel="lightbox" src="$j.small_photo_url" alt="" /></span> <br clear="all"> </a>
		<a href="$j.page_url"><h3>$j.name</h3></a>
		</div>
	#end for
	</div>
	<ul class="inline footer">
	<li>&gt; <a href="index.html" title="Top">Top</a></li>
	</ul>
#end for
</body>
</html>

例えば、以下のファイルをogura.txtとして保存して、

Ogura Yuko, 小倉優子

以下のようにindex.htmlを生成した場合、

%python flickr.py -d ogura.txt
%python flickr.py -m ogura.txt > index.html

以下のファイルが生成されます。

お楽しみください。