根据rauth示例中的twitter
脚本,我使用rauth
(OAuth1
)实现了twitter-timeline-cli.py
客户端的以下实现:
from rauth.service import OAuth1Service
class TwitterClient:
KNOWN_USERS = {
'user1' : ("xxx", "yyy", "2342354"), # These should be real tokens
}
def __init__(self):
# Get a real consumer key & secret from https://dev.twitter.com/apps/new
self.twitter = OAuth1Service(
name='twitter',
consumer_key=TWITTER_CONSUMER_KEY,
consumer_secret=TWITTER_CONSUMER_SECRET,
request_token_url='https://api.twitter.com/oauth/request_token',
access_token_url='https://api.twitter.com/oauth/access_token',
authorize_url='https://api.twitter.com/oauth/authorize',
base_url='https://api.twitter.com/1/')
def authorize(self):
request_token, request_token_secret = self.twitter.get_request_token()
authorize_url = self.twitter.get_authorize_url(request_token)
print 'Visit this URL in your browser: ' + authorize_url
pin = raw_input('Enter PIN from browser: ')
return request_token, request_token_secret, pin
def init_session(self, user):
if user in self.KNOWN_USERS :
request_token, request_token_secret, pin = self.KNOWN_USERS[user]
else:
request_token, request_token_secret, pin = self.authorize()
session = self.twitter.get_auth_session(request_token,
request_token_secret,
method='POST',
data={'oauth_verifier': pin})
return session
def list_tweets(self, user):
session = self.init_session(user)
params = {'include_rts': 1, # Include retweets
'count': 10} # 10 tweets
r = session.get('statuses/home_timeline.json', params=params)
for i, tweet in enumerate(r.json(), 1):
handle = tweet['user']['screen_name'].encode('utf-8')
text = tweet['text'].encode('utf-8')
print '{0}. @{1} - {2}'.format(i, handle, text)
tc = TwitterClient()
tc.list_tweets('user1')
这个想法是,如果用户不知道,则要求他授权该应用程序。另一方面,如果用户已经授权此应用程序,则应重用授权令牌(request_token,request_token_secret,pin)(通常令牌将在数据库中;暂时,它们在硬盘中被硬编码脚本)
但这不起作用:
Traceback (most recent call last):
File "my-twitter-timeline-cli.py", line 56, in <module>
tc.list_tweets('user1')
File "my-twitter-timeline-cli.py", line 43, in list_tweets
session = self.init_session(user)
File "my-twitter-timeline-cli.py", line 39, in init_session
data={'oauth_verifier': pin})
File ".../lib/python2.7/site-packages/rauth/service.py", line 326, in get_auth_session
**kwargs)
File ".../lib/python2.7/site-packages/rauth/service.py", line 299, in get_access_token
process_token_request(r, decoder, key_token, key_token_secret)
File ".../lib/python2.7/site-packages/rauth/service.py", line 25, in process_token_request
raise KeyError(PROCESS_TOKEN_ERROR.format(key=bad_key, raw=r.content))
KeyError: 'Decoder failed to handle oauth_token with data as returned by provider. A different decoder may be needed. Provider returned: <?xml version="1.0" encoding="UTF-8"?>\n<hash>\n <error>Invalid / expired Token</error>\n <request>/oauth/access_token</request>\n</hash>\n'
是否可以重复使用OAuth1
授权令牌?
答案 0 :(得分:15)
我误解了整个过程。我们不需要保存request_token
,request_token_secret
和pin
,而是保存access_token
和access_token_secret
。
这个过程实际上是:
request_token
,request_token_secret
和pin
获取access_token
和access_token_secret
access_token
和access_token_secret
(到数据库,或其他)access_token
和access_token_secret
这是我更正的测试代码:
from rauth.service import OAuth1Service
class TwitterClient:
KNOWN_USERS = { # (access_token, access_token_secret)
'user1' : ("xxx", "yyy")
}
def __init__(self):
# Get a real consumer key & secret from https://dev.twitter.com/apps/new
self.twitter = OAuth1Service(
name='twitter',
consumer_key=TWITTER_CONSUMER_KEY,
consumer_secret=TWITTER_CONSUMER_SECRET,
request_token_url='https://api.twitter.com/oauth/request_token',
access_token_url='https://api.twitter.com/oauth/access_token',
authorize_url='https://api.twitter.com/oauth/authorize',
base_url='https://api.twitter.com/1/')
def new_session(self):
request_token, request_token_secret = self.twitter.get_request_token()
authorize_url = self.twitter.get_authorize_url(request_token)
print 'Visit this URL in your browser: ' + authorize_url
pin = raw_input('Enter PIN from browser: ')
session = self.twitter.get_auth_session(request_token,
request_token_secret,
method='POST',
data={'oauth_verifier': pin})
print session.access_token, session.access_token_secret # Save this to database
return session
def reuse_session(self, user):
access_token, access_token_secret = self.KNOWN_USERS[user]
session = self.twitter.get_session((access_token, access_token_secret))
return session
def init_session(self, user):
if user in self.KNOWN_USERS : session = self.reuse_session(user)
else : session = self.new_session()
return session
def list_tweets(self, user):
session = self.init_session(user)
params = {'include_rts': 1, # Include retweets
'count': 10} # 10 tweets
r = session.get('statuses/home_timeline.json', params=params)
for i, tweet in enumerate(r.json(), 1):
handle = tweet['user']['screen_name'].encode('utf-8')
text = tweet['text'].encode('utf-8')
print '{0}. @{1} - {2}'.format(i, handle, text)
tc = TwitterClient()
tc.list_tweets('user1')