python-box:appengine-twitter
差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
python-box:appengine-twitter [2009/07/12 22:31] – dgbadmin | python-box:appengine-twitter [2017/05/13 05:36] (現在) – [AppEngine-Twitterのソースコード] dgbadmin | ||
---|---|---|---|
行 1: | 行 1: | ||
====== Google App Engineで手軽にTwitterアプリを作成!(OAuthにも対応!) - AppEngine-Twitter ====== | ====== Google App Engineで手軽にTwitterアプリを作成!(OAuthにも対応!) - AppEngine-Twitter ====== | ||
+ | |||
+ | 更新履歴とコメントは[[http:// | ||
{{: | {{: | ||
行 5: | 行 7: | ||
Google App EngineでTwitter APIを操作するライブラリを作ってみた。\\ | Google App EngineでTwitter APIを操作するライブラリを作ってみた。\\ | ||
車輪の再発明ではなく、趣味の車輪作り。 | 車輪の再発明ではなく、趣味の車輪作り。 | ||
+ | |||
+ | バージョン0.3.0からはTwitter Search APIの廃止に対応して、検索もOAuthを使ってTwitter REST API 1.1を使うように変更した。 | ||
行 13: | 行 17: | ||
===== デモ(動作サンプル) ===== | ===== デモ(動作サンプル) ===== | ||
- | |||
- | ※OAuthを使っているデモについては[[python-box/ | ||
- | |||
==== その1. RT(ReTweet)の多いつぶやきを報告するBot ==== | ==== その1. RT(ReTweet)の多いつぶやきを報告するBot ==== | ||
行 21: | 行 22: | ||
- | ==== その2. ユーザー名・パスワードを入力してTwitter APIの主な操作を一通りするデモ | + | ==== その2. |
- | [[http://0-oo.appspot.com/twitter/|ユーザー名・パスワードを入力してTwitter APIの主な操作を一通りするデモ]] | + | [[http://twitter.com/who_is_near|@who_is_near]] |
- | ソースコード(※[[python-box/ | + | ※検索がまだTwitter REST API 1.1に対応させてないので今は動かない(はず) |
- | <code python> | + | |
- | # | + | |
- | # -*- coding: UTF-8 -*- | + | |
- | ''' | + | |
- | Sample for AppEngine-Twitter on Google App Engine | + | |
- | See: http://0-oo.net/sbox/ | + | === 使用例 === |
- | ''' | + | < |
+ | 試しにつぶやくには、Twitterにログイン後に[[http://twitter.com/? | ||
- | import logging | ||
- | import wsgiref.handlers | ||
- | from appengine_twitter import AppEngineTwitter | ||
- | from basehandler import BaseHandler, | ||
- | from google.appengine.ext import webapp | ||
+ | ==== その3. 出発地点と目的地を告げると、乗換(ルート)案内のGoogleマップを表示してくれるBot ==== | ||
+ | [[http:// | ||
- | class MainHandler(BaseHandler): | + | === 使用例 1. 移動方法を指定しないと、電車でのルート検索・乗り換え案内になる |
- | + | <code>@norikae_map 東京 大阪</code> | |
- | def get(self): | + | 試しにつぶやくには、Twitterにログイン後に[[http:// |
- | self.show() | + | |
- | + | ||
- | + | ||
- | def post(self): | + | |
- | self.show(self.request.get(' | + | |
- | + | ||
- | + | ||
- | def show(self, name='', | + | |
- | self.simple_header(u' | + | |
- | + | ||
- | self.p(u'< | + | |
- | self.p(u'< | + | |
- | self.p('< | + | |
- | self.p(u' | + | |
- | self.p('< | + | |
- | | + | |
- | self.p(' | + | |
- | ' value="' | + | |
- | self.p(' | + | |
- | self.p(' | + | |
- | | + | |
- | + | ||
- | if name and pswd: | + | |
- | self.test(name, | + | |
- | + | ||
- | self.p('< | + | |
- | self.p(u' | + | |
- | self.p('< | + | |
- | self.p(' | + | |
- | self.p(u'< | + | |
- | + | ||
- | self.simple_footer() | + | |
- | + | ||
- | + | ||
- | def test(self, name, pswd): | + | |
- | twitter | + | |
- | + | ||
- | self.p(u'< | + | |
- | + | ||
- | self.p(u'< | + | |
- | self.p(twitter.verify(), | + | |
- | self.p('< | + | |
- | + | ||
- | self.p(u'< | + | |
- | results = twitter.search(u' | + | |
- | for result in results: | + | |
- | self.p(result[' | + | |
- | self.p('< | + | |
- | + | ||
- | self.p(u'< | + | |
- | if twitter.is_following(' | + | |
- | self.p(' | + | |
- | else: | + | |
- | self.p(' | + | |
- | self.p('< | + | |
- | + | ||
- | note = u'< | + | |
- | note += u' | + | |
- | self.p(note, | + | |
- | self.p(twitter.follow(' | + | |
- | self.p('< | + | |
- | self.p(u'<b>update()</b> つぶやく(200なら成功。自分のTLを見てみてね)', | + | === 使用例 2. 車でのルートの案内 === |
- | msg = ' | + | <code>@norikae_map 木更津駅 羽田空港駅 車</code> |
- | msg += u'http://0-oo.appspot.com/twitter/ からこんにちは!' | + | 試しにつぶやくには、Twitterにログイン後に[[http://twitter.com/? |
- | self.p(twitter.update(msg.encode(' | + | |
- | self.p('< | + | |
+ | === 使用例 3. 歩きでのルートの案内 === | ||
+ | < | ||
+ | 試しにつぶやくには、Twitterにログイン後に[[http:// | ||
- | logging.getLogger() | + | ==== その4. Twitter APIでOAuth認証してつぶやいたりフォローしたりするデモ ==== |
- | routing | + | |
- | application | + | |
- | wsgiref.handlers.CGIHandler().run(application) | + | |
- | </ | + | |
+ | [[python-box/ | ||
行 135: | 行 66: | ||
See also: | See also: | ||
- | | + | |
- | | + | |
''' | ''' | ||
__author__ = ' | __author__ = ' | ||
- | __version__ = '0.1.0' | + | __version__ = '0.4.0' |
- | import | + | import |
import urllib | import urllib | ||
from appengine_oauth import AppEngineOAuth | from appengine_oauth import AppEngineOAuth | ||
- | from django.utils import simplejson | ||
from google.appengine.api import urlfetch | from google.appengine.api import urlfetch | ||
- | + | ||
class AppEngineTwitter(object): | class AppEngineTwitter(object): | ||
- | def __init__(self, tw_name='', | + | def __init__(self): |
- | ''' | + | self._api_url = ' |
- | Note: Some actions require password or OAuth. | + | self._oauth_url |
- | ''' | + | |
- | self._api_url = ' | + | |
- | self._search_url | + | |
- | + | ||
- | self.tw_name = tw_name | + | |
self._oauth = None | self._oauth = None | ||
- | | + | self._tw_name |
- | | + | |
- | if tw_pswd != '': | + | |
- | auth = base64.encodestring(tw_name + ':' | + | |
- | self._headers[' | + | |
- | + | ||
def update(self, | def update(self, | ||
行 173: | 行 94: | ||
Sucess => Retrun 200 / Fialed => Return other HTTP status | Sucess => Retrun 200 / Fialed => Return other HTTP status | ||
''' | ''' | ||
- | return self._post(' | + | return self._post(' |
- | + | ||
+ | |||
+ | def retweet(self, | ||
+ | ''' | ||
+ | ReTweet a tweet | ||
+ | Sucess => Retrun 200 / Fialed => Return other HTTP status | ||
+ | ''' | ||
+ | return self._post(' | ||
def follow(self, | def follow(self, | ||
行 181: | 行 110: | ||
Fialed => Return other HTTP status | Fialed => Return other HTTP status | ||
''' | ''' | ||
- | return self._post(' | + | return self._post(' |
- | + | ||
def is_following(self, | def is_following(self, | ||
行 189: | 行 118: | ||
Fialed => Return HTTP status except 200 | Fialed => Return HTTP status except 200 | ||
''' | ''' | ||
- | if self.tw_name | + | if self._tw_name |
- | # With OAuth, screen_name is not required. | + | |
self.verify() | self.verify() | ||
- | user_info = simplejson.loads(self.last_response.content) | + | user_info = json.loads(self.last_response.content) |
- | self.tw_name | + | self._tw_name |
- | + | ||
- | status = self._get(' | + | status = self._get(' |
- | | + | |
if status == 200: | if status == 200: | ||
return (self.last_response.content == ' | return (self.last_response.content == ' | ||
行 208: | 行 136: | ||
Sucess => Return 200 / Fialed => Return other HTTP status | Sucess => Return 200 / Fialed => Return other HTTP status | ||
''' | ''' | ||
- | return self._get(' | + | return self._get(' |
- | + | ||
def search(self, | def search(self, | ||
''' | ''' | ||
- | Sucess => Return Array of dict / Fialed => Return HTTP status except 200 | + | Sucess => Return Array of dict / Fialed => raise an Exception |
''' | ''' | ||
params[' | params[' | ||
- | | + | |
+ | |||
+ | if status == 200: | ||
+ | return json.loads(self.last_response.content)[' | ||
+ | else: | ||
+ | raise Exception(' | ||
行 233: | 行 166: | ||
Get request token, request token secret and login URL | Get request token, request token secret and login URL | ||
''' | ''' | ||
- | dic = self._oauth.prepare_login(self._api_url | + | dic = self._oauth.prepare_login(self._oauth_url |
- | dic[' | + | dic[' |
return dic | return dic | ||
行 242: | 行 175: | ||
Exchange request token for access token | Exchange request token for access token | ||
''' | ''' | ||
- | return self._oauth.exchange_tokens(self._api_url | + | return self._oauth.exchange_tokens(self._oauth_url |
| | ||
| | ||
行 248: | 行 181: | ||
# Private methods | # Private methods | ||
- | + | ||
def _post(self, path, params): | def _post(self, path, params): | ||
url = self._api_url + path | url = self._api_url + path | ||
- | | + | params = self._oauth.get_oauth_params(url, |
- | | + | res = urlfetch.fetch(url=url, |
- | res = urlfetch.fetch(url=url, | + | |
- | payload=urllib.urlencode(params), | + | |
- | method=' | + | |
- | | + | |
self.last_response = res | self.last_response = res | ||
return res.status_code | return res.status_code | ||
- | + | ||
def _get(self, path, params): | def _get(self, path, params): | ||
行 266: | 行 195: | ||
params = self._oauth.get_oauth_params(url, | params = self._oauth.get_oauth_params(url, | ||
url += '?' | url += '?' | ||
- | res = urlfetch.fetch(url=url, | + | res = urlfetch.fetch(url=url, |
self.last_response = res | self.last_response = res | ||
return res.status_code | return res.status_code | ||
- | |||
- | |||
- | def _search(self, | ||
- | ''' | ||
- | FYI http:// | ||
- | ''' | ||
- | url = url=self._search_url + path + '?' | ||
- | res = urlfetch.fetch(url=url, | ||
- | self.last_response = res | ||
- | | ||
- | if res.status_code == 200: | ||
- | return simplejson.loads(res.content)[' | ||
- | elif res.status_code == 503: | ||
- | err_msg = 'Rate Limiting: Retry After ' + res.headers[' | ||
- | else: | ||
- | err_msg = ' | ||
- | |||
- | raise Exception(' | ||
</ | </ | ||
python-box/appengine-twitter.1247405517.txt.gz · 最終更新: 2009/07/12 22:31 by dgbadmin