Python で Stack Stock Books API モジュール的なもの
読書管理に Stack Stock Books を利用しています。まあ読書管理してても、積まれてる本の数は全然減らないんですが…
で、なんか面白そうな本ないかなーって時に、ここのつぶやき(参加ユーザーの読書メモ的なもの)をザザーっと眺めたりするのが好きなんです。このつぶやき一覧を Stack Stock Books の API で取得できるので、bit.ly の機能限定 API モジュール に続いて、Stack Stock Books API の Python モジュールを書き散らかしてみました。
今のところの機能としては
- つぶやき一覧取得(include_authors は未実装)
- 利用者情報
だけ。
例によって simplejson を使ってます。
ssb.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import urllib import urllib2 from datetime import datetime import logging import simplejson as json #logging.basicConfig(level=logging.DEBUG) class SSBError(Exception): """Base class for SSB errors """ pass class SSBRequestError(SSBError): """SSB API request error class """ def __init__(self, code, msg): self.code = code self.msg = msg def __str__(self): return "SSB API request error: %s (code: %s)" % (self.msg, self.code) class SSBResponseError(SSBError): """SSB API response error class """ def __init__(self, msg): self.msg = msg def __str__(self): return "SSB API response error: %s" % self.msg class Mumble(object): """つぶやきクラス """ def __init__(self, mumble_id=None, body=None, time=None, user_id=None, book_id=None, book=None): self.mumble_id = mumble_id self.body = body self.time = time self.user_id = user_id self.book_id = book_id self.book = book @property def uri(self): return "http://stack.nayutaya.jp/book/%(isbn10)s/mumble/%(mumble_id)s" \ % dict(isbn10=self.book.isbn10, mumble_id=self.mumble_id) def get_mumble_id(self): return self._mumble_id def set_mumble_id(self, val): self._mumble_id = val mumble_id = property(get_mumble_id, set_mumble_id, doc="The unique id of this mumble.") def get_body(self): return self._body def set_body(self, val): self._body = val body = property(get_body, set_body, doc="The text of this mumble.") def get_time(self): return self._time def set_time(self, val): try: sdate, stime = val.split() args = [int(arg) for arg in sdate.split("-") + stime.split(":")] self._time = datetime(*args) except: self._time = None time = property(get_time, set_time, doc="The time this mumble was posted.") def get_user_id(self): return self._user_id def set_user_id(self, val): self._user_id = val user_id = property(get_user_id, set_user_id, doc="The unique id of the user who posted this mumble.") def get_book_id(self): return self._book_id def set_book_id(self, val): self._book_id = val book_id = property(get_book_id, set_book_id, doc="The unique id of the book mentioned in this mumble.") def get_book(self): return self._book def set_book(self, val): self._book = val book = property(get_book, set_book, doc="The book object which mentioned in this mumble.") def as_dict(self): """Mumble インスタンスを辞書として返す """ data = {} if self.mumble_id: data['mumble_id'] = self.mumble_id if self.body: data['body'] = self.body if self.time: data['time'] = self.time.strftime('%Y-%m-%d %H:%M:%S') if self.user_id: data['user_id'] = self.user_id if self.book_id: data['book_id'] = self.book_id if self.book: data['book'] = self.book.as_dict() return data def as_json_string(self): """Mumble インスタンスを JSON 文字列として返す """ return json.dumps(self.as_dict(), sort_keys=True) def __str__(self): return self.as_json_string() @staticmethod def new_from_json_dict(data): if 'book' in data: book = Book.new_from_json_dict(data['book']) else: book = None return Mumble(mumble_id=data.get('mumble_id'), body=data.get('body'), time=data.get('time'), user_id=data.get('user_id'), book_id=data.get('book_id'), book=book) class Book(object): """書籍蔵書クラス""" def __init__(self, book_id=None, isbn10=None, isbn13=None, title=None, release_date=None, binding=None, publisher=None, uri=None, image_uri=None): self.book_id = book_id self.isbn10 = isbn10 self.isbn13 = isbn13 self.title = title self.release_date = release_date self.binding = binding self.publisher = publisher self.uri = uri self.image_uri = image_uri def get_book_id(self): return self._book_id def set_book_id(self, val): self._book_id = val book_id = property(get_book_id, set_book_id, doc="The unique id of this book.") def get_isbn10(self): return self._isbn10 def set_isbn10(self, val): self._isbn10 = val isbn10 = property(get_isbn10, set_isbn10, doc="The isbn 10 of this book.") def get_isbn13(self): return self._isbn13 def set_isbn13(self, val): self._isbn13 = val isbn13 = property(get_isbn13, set_isbn13, doc="The isbn 13 of this book.") def get_title(self): return self._title def set_title(self, val): self._title = val title = property(get_title, set_title, doc="The title of this book.") def get_release_date(self): return self._release_date def set_release_date(self, val): """ try: sdate, stime = val.split() args = [int(arg) for arg in sdate.split("-") + stime.split(":")] self._release_date = datetime(*args) except: self._release_date = None """ self._release_date = val release_date = property(get_release_date, set_release_date, doc="Date when this book was released.") def get_binding(self): return self._binding def set_binding(self, val): self._binding = val binding = property(get_binding, set_binding, doc="The binding of this book.") def get_publisher(self): return self._publisher def set_publisher(self, val): self._publisher = val publisher = property(get_publisher, set_publisher, doc="The publisher of this book.") def get_uri(self): return self._uri def set_uri(self, val): self._uri = val uri = property(get_uri, set_uri, doc="The uri of this book.") def get_image_uri(self): return self._image_uri def set_image_uri(self, val): self._image_uri = val image_uri = property(get_image_uri, set_image_uri, doc="The image uri of this book.") def as_dict(self): """Book インスタンスを辞書として返す """ data = {} if self.book_id: data['book_id'] = self.book_id if self.isbn10: data['isbn10'] = self.isbn10 if self.isbn13: data['isbn13'] = self.isbn13 if self.title: data['title'] = self.title if self.release_date: data['release_date'] = self.release_date if self.binding: data['binding'] = self.binding if self.publisher: data['publisher'] = self.publisher if self.uri: data['uri'] = self.uri if self.image_uri: data['image_uri'] = self.image_uri return data def as_json_string(self): """Book インスタンスを JSON 文字列として返す """ return json.dumps(self.as_dict(), sort_keys=True) def __str__(self): return self.as_json_string() def __eq__(self, other): return str(self) == str(other) def __ne__(self, other): return not self.__eq__(other) @staticmethod def new_from_json_dict(data): """ """ return Book(book_id=data.get('book_id'), isbn10=data.get('isbn10'), isbn13=data.get('isbn13'), title=data.get('title'), release_date=data.get('release_date'), binding=data.get('binding'), publisher=data.get('publisher'), uri=data.get('uri'), image_uri=data.get('image_uri')) class User(object): """ユーザークラス""" def __init__(self, user_id=None, name=None, nick=None, uri=None, icon_uri=None): self.user_id = user_id self.name = name self.nick = nick self.uri = uri self.icon_uri = icon_uri def get_user_id(self): return self._user_id def set_user_id(self, val): self._user_id = val user_id = property(get_user_id, set_user_id, doc="The unique id of this user.") def get_name(self): return self._name def set_name(self, val): self._name = val name = property(get_name, set_name, doc="The name of this user.") def get_nick(self): return self._nick def set_nick(self, val): self._nick = val nick = property(get_nick, set_nick, doc="The nickname of this user.") def get_uri(self): return self._uri def set_uri(self, val): self._uri = val uri = property(get_uri, set_uri, doc="The uri of this user.") def get_icon_uri(self): return self._icon_uri def set_icon_uri(self, val): self._icon_uri = val icon_uri = property(get_icon_uri, set_icon_uri, doc="The icon uri of this user.") def as_dict(self): """User インスタンスを辞書として返す """ data = {} if self.user_id: data['user_id'] = self.user_id if self.name: data['name'] = self.name if self.nick: data['nick'] = self.nick if self.uri: data['uri'] = self.uri if self.icon_uri: data['icon_uri'] = self.icon_uri return data def as_json_string(self): """User インスタンスを JSON 文字列として返す """ return json.dumps(self.as_dict(), sort_keys=True) def __str__(self): return self.as_json_string() def __eq__(self, other): return str(self) == str(other) def __nq__(self, other): return not self.__eq__(other) @staticmethod def new_from_json_dict(data): return User(user_id=data.get('user_id'), name=data.get('name'), nick=data.get('nick'), uri=data.get('uri'), icon_uri=data.get('icon_uri')) class Api(object): """Stack Stock Books API クラス """ USER_ID_TYPE_ID = "id" USER_ID_TYPE_NAME = "name" ORDER_ASC = "mumble_id_asc" ORDER_DESC = "mumble_id_desc" def __init__(self): self.base_url = "http://stack.nayutaya.jp/api" def get_mumbles(self, include_books=True, include_authors=False, order=ORDER_DESC, page=1): """つぶやき一覧取得 TODO: include_authors は現在未実装 """ api_name = 'get_mumbles' query_dict = {} if include_books: query_dict['include_books'] = 'true' if order != self.ORDER_DESC: query_dict['order'] = self.ORDER_ASC if page > 1: query_dict['page'] = page query = urllib.urlencode(query_dict) url = "%s/mumbles.json?%s" % (self.base_url, query) logging.debug("[%s]: url: %s", api_name, url) data = self._get_data(api_name, url) return [Mumble.new_from_json_dict(m) for m in data['response']['mumbles']] def get_user(self, user_id, user_id_type=USER_ID_TYPE_ID): """利用者情報取得 """ api_name = 'get_user' url = "%s/user/%s/%s.json" % (self.base_url, user_id_type, user_id) logging.debug("[%s]: url: %s", api_name, url) data = self._get_data(api_name, url) logging.debug("[%s]: %s", api_name, data['response']['user']) return User.new_from_json_dict(data['response']['user']) def _get_data(self, api_name, url): """指定 API を実行して結果を返す """ data = {} f = urllib2.urlopen(url) try: if not (200 <= f.code < 300): e = SSBRequestError(f.code, f.msg) logging.error("[%s] SSBRequestError: %s", api_name, e) raise e data = json.load(f) finally: f.close() self._check_api_success(api_name, data) return data def _check_api_success(self, api_name, data): """API 処理が失敗したら例外を発生させる """ if data.get('success', True): return e = SSBResponseError(data.get('success', True)) raise e
使い方は、
>>> import ssb >>> api = ssb.Api() >>> m = api.get_mumbles()[0] >>> print m.book.title Python ポケットリファレンス (Pocket Reference) >>> print m.body 結構いい本 >>> u = api.get_user(m.user_id) >>> print u.nick namaco
こんな感じです。