ユーザーデータ取得処理
Twitterのユーザデータを保存するためのクラス(Kind)を定義したところで、次はTwitterからユーザデータを取得する処理を実装します。処理の概要は中編の図7などを参照してください。
初期データ作成処理
本稿のアプリケーションでは、最初の1件のユーザを追加する処理は、開発者がブラウザからURLを入力し動作させる必要があります。以下に実装について説明します。
初期データ作成用リクエストハンドラ
初期データを作成するための処理URLは「http://ホスト名/ciu」というURLでアクセスします。このURLのためのリクエストハンドラはmain.pyに以下のように記述します。
class CreateInitUserHandler(webapp.RequestHandler): # 初期ユーザ1件を作成するためのメソッド def get(self): screen_name = 'haru860' # 初期ユーザのscreen_name _put_tw_user(screen_name) # TwitterUserの保存 _put_wait_get_related_data(screen_name) # 擬似キューへの保存
リクエストハンドラとは、HTTPのメソッド(GETや、POST)を受け付ける処理で、getやpostという名前のメソッドにリクエスト受付時の処理を実装します。
リクエストハンドラのアプリケーションへの追加
リクエストハンドラをアプリケーションに追加するには、リスト3のようにwebapp.WSGIApplicationのコンストラクタにURLのマッピングとハンドラクラスを渡し、インスタンスを生成します。その後、wsgiref.handlers.CGIHandler().run(application)で、アプリケーションが起動されます。
def main(): application = webapp.WSGIApplication([ ('/', MainHandler) ('/ciu', CreateInitUserHandler), ], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main()
Twitterユーザ生成処理
_put_tw_userメソッドは、引数で渡されたscreen_nameに該当するTwitterのユーザデータをDatastoreに保存する処理です。ソースを以下に示します。
from models import TwitterUser import twitterutil as twutil def _put_tw_user(screen_name): # screen_nameに該当するデータを取得する tw_user = TwitterUser.get_by_key_name(screen_name) # 既に存在する場合は、そのデータを返す if tw_user != None: return tw_user # Twitter APIにアクセスしてユーザデータを取得する user = twutil.create_twitter_user(screen_name) # Counterクラスから連番を取得する user.seq = Counter.next_id('TwitterUser') user.put() return user
次にTwitterのユーザ属性取得API(http://twitter.com/users/show/$screen_name.xml)にアクセスし、ユーザデータを取得するcreate_twitter_userメソッドを以下に示します。
def create_twitter_user(screen_name): url = 'http://twitter.com/users/show/' + screen_name + '.xml' return _create_twitter_user_by_xmlstr(_get_api_response(url))
get_api_responseメソッドは引数で指定されたURLにアクセスし、レスポンス文字列を返すメソッドです。ここでは、取得したXML文字列を_create_twitter_user_by_xmlstrメソッドに渡して、TwitterUserエンティティを返しています。_get_api_responseメソッドと_create_twitter_user_by_elementメソッドのソースをそれぞれリスト6、7 に示します。
def _get_api_response(url): # ベーシック認証でTwitterにアクセスする base64string = base64.encodestring("%s:%s" % ("haru860", "passwordxx"))[:-1] headers = {"Authorization": "Basic %s" % base64string} # URL Fetch APIを使用 return urlfetch.fetch(url,payload=None,method=urlfetch.GET,headers=headers).content
def _create_twitter_user_by_xmlstr(xml_string): user_elem = etree.fromstring(xml_string) return _create_twitter_user_by_element(user_elem)
リスト7から呼んでいる_create_twitter_user_by_elementメソッドはXML要素をもとにTwitterUserエンティティを返すメソッドですが、ここではソースの説明を割愛します。
Counter用クラス
リスト3ではCounterクラスのnext_idメソッドを呼び出して連番を取得していますが、Counterクラスはその名前の通り、連番を生成するためのクラスです。以下にCounterクラスのソースを示します。
class Counter(db.Model): count = db.IntegerProperty() @classmethod def next_id(cls, name): def txn(): obj = cls.get_by_key_name(name) if obj is None: obj = cls(key_name=name,count=0) obj.count += 1 obj.put() return obj.count return db.run_in_transaction(txn)
next_idメソッドは、引数にカウンタの名前を取り、その名前ごとのカウンタ値を保持したエンティティをDatastoreに保存します。next_idメソッド内では、txn()という関数オブジェクトを作成し、db.run_in_transaction(txn)に引数で渡しています。これは引数で渡した関数オブジェクト内に記述された処理のトランザクションを保証するための仕組みです。
関連ユーザデータ収集用エンティティ格納処理
リスト2の初期データ作成用ハンドラ(CreateInitUserHandler)のpostメソッドでは、新規TwitterUserエンティティを1件作成すると同時に、WaitGetRelatedDataエンティティを1件作成します。WaitGetRelatedDataエンティティは、中編のユーザデータ取得処理で説明しているように、擬似的なキューとして使用されるエンティティです。_put_wait_get_related_dataは引数で渡されたscreen_nameをWaitGetRelatedDataエンティティの属性に格納してDatastoreに保存するという単純な処理なのでソースは割愛します。