文章来源:http://qinxuye.me/article/sina-weibo-api-in-developing-diango/
Update:如果想了解更多第三方帐号登录,请看这篇文章。
随着新浪微博用户日益增加,我们有时候会考虑在自己的网站中整合新浪微博。比如说我现在的独立博客。
在我的博客中做到整合主要就这几方面:我写一篇文章,就会同步发送至微博。同时呢,用户可以用微博帐号登录,并且可以选择把对文章的评论,同步评论到文章的微博。另外,用户可以选择是否把博客留言同步至新浪微博。
首先要涉及的问题,就是用户用新浪微博帐号登录的问题,即授权机制。基本方法有两种:
- OAuth
- Basic auth(需要强调的是,微博开放平台将于6月1日正式停止Basic Auth的支持。因此,此种方法不作讨论了,其实需要用户名和密码的方式本身就不安全。)
OAuth新浪官方的文档在这里。想要了解OAuth技术说明的可以访问官方网站。
其实,OAuth的流程还是很简单的。大致如下:
- 向API调用获得request token。
- 将用户重定向到授权页(auth url)。
- 用户输入用户名和密码完成授权。重定向到Callback_url。
- 用request token向新浪微博换取access token。
- 完成。
大致了解了OAuth的原理以后,由于我们是整合至Django,自然需要下载微博SDK的Python版。
不过,在全部开始前,你得先向新浪微博申请你的应用。申请地址在这里。这里要强调的是,日后应用需要申请审核,因为只有审核通过后,在来源中才能显示个性的应用名。所以,在申请的时候,注意应用介绍信息的完整,以及应用分类的填写正确。(在本例中,我们的分类是合作网站。)
申请完成以后将会得到你的应用的App Key和App Secret。
回到授权用户登录的话题。允许新浪微博帐号接入,首先我们需要在urlpatterns中添加几个URL。如下:
1
2
3
4
5
|
urlpatterns
=
patterns(
'projectname.appname.views'
,
url(r
'^log/$'
,
'login'
, name
=
'log'
),
url(r
'^logincheck/$'
,
'login_check'
, name
=
'logcheck'
),
url(r
'^logout/$'
,
'logout'
, name
=
'logout'
),
)
|
接着,我们开始views文件。代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
基于django的新浪微博oauth views
需要django的session支持
"""
from
django.http
import
HttpResponseRedirect
from
weibopy.auth
import
OAuthHandler, WeibopError
from
weibopy
import
oauth
consumer_key
=
''
# 设置你申请的appkey
consumer_secret
=
''
# 设置你申请的appkey对于的secret
class
WebOAuthHandler(OAuthHandler):
def
get_authorization_url_with_callback(
self
, callback, signin_with_twitter
=
False
):
"""Get the authorization URL to redirect the user"""
try
:
# get the request token
self
.request_token
=
self
._get_request_token()
# build auth request and return as url
if
signin_with_twitter:
url
=
self
._get_oauth_url(
'authenticate'
)
else
:
url
=
self
._get_oauth_url(
'authorize'
)
request
=
oauth.OAuthRequest.from_token_and_callback(
token
=
self
.request_token, callback
=
callback, http_url
=
url
)
return
request.to_url()
except
Exception, e:
raise
WeibopError(e)
def
_get_referer_url(request):
referer_url
=
request.META.get(
'HTTP_REFERER'
,
'/'
)
host
=
request.META[
'HTTP_HOST'
]
if
referer_url.startswith(
'http'
)
and
host
not
in
referer_url:
referer_url
=
'/'
# 避免外站直接跳到登录页而发生跳转错误
return
referer_url
def
_oauth():
"""获取oauth认证类"""
return
WebOAuthHandler(consumer_key, consumer_secret)
def
login(request):
# 保存最初的登录url,以便认证成功后跳转回来
back_to_url
=
_get_referer_url(request)
request.session[
'login_back_to_url'
]
=
back_to_url
# 获取oauth认证url
login_backurl
=
request.build_absolute_uri(
'/logincheck'
)
auth_client
=
_oauth()
auth_url
=
auth_client.get_authorization_url_with_callback(login_backurl)
# 保存request_token,用户登录后需要使用它来获取access_token
request.session[
'oauth_request_token'
]
=
auth_client.request_token
# 跳转到登录页面
return
HttpResponseRedirect(auth_url)
def
login_check(request):
"""用户成功登录授权后,会回调此方法,获取access_token,完成授权"""
verifier
=
request.GET.get(
'oauth_verifier'
,
None
)
auth_client
=
_oauth()
# 设置之前保存在session的request_token
request_token
=
request.session[
'oauth_request_token'
]
del
request.session[
'oauth_request_token'
]
auth_client.set_request_token(request_token.key, request_token.secret)
access_token
=
auth_client.get_access_token(verifier)
# 保存access_token,以后访问只需使用access_token即可
request.session[
'oauth_access_token'
]
=
access_token
# 跳转回最初登录前的页面
back_to_url
=
request.session.get(
'login_back_to_url'
,
'/'
)
return
HttpResponseRedirect(back_to_url)
def
logout(request):
"""用户登出,直接删除access_token"""
del
request.session[
'oauth_access_token'
]
back_to_url
=
_get_referer_url(request)
return
HttpResponseRedirect(back_to_url)
|
在完成了授权的代码之后,接着我们就要知道如何向新浪微博作发送消息等操作了。其实,在下载的SDK下的exanples文件夹(没错,其实是examples,这英文水平,吐槽不能)中的例子基本上拿来改改就可以直接使用了。拿oauthSetTokenUpdate.py来说,我们就可以照着这么写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# -*- coding: utf-8 -*-
from
weibopy.auth
import
OAuthHandler
from
weibopy.api
import
API
consumer_key
=
'应用的key'
consumer_secret
=
'应用的App Secret'
auth
=
OAuthHandler(consumer_key, consumer_secret)
auth_url
=
auth.get_authorization_url()
print
'Please authorize: '
+
auth_url
verifier
=
raw_input
(
'PIN: '
).strip()
auth.get_access_token(verifier)
api
=
API(auth)
status
=
api.update_status(status
=
'hello world'
, lat
=
'12.3'
,
long
=
'45.6'
)
# 注意status必须是UTF-8编码的字符串,经纬度是可以不写的
print
status.
id
print
status.text
|
运行这个程序就会提示一个URL链接,在浏览器里打开这个链接,并且给予访问权限,就会拿到一串PIN码。把这个PIN码输上去,就会发送一条推了,并且还会显示用户的Access token key和Access token secret。
不过呢,这么做是不是有点太nerd了。其实我们只要知道Access token key和Access token secret之后,就可以直接用它们来创建API对象了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# -*- coding: utf-8 -*-
from
weibopy.auth
import
OAuthHandler
from
weibopy.api
import
API
consumer_key
=
'应用的key'
consumer_secret
=
'应用的App Secret'
token
=
'用户的Access token key'
tokenSecret
=
'用户的Access token secret'
auth
=
OAuthHandler(consumer_key, consumer_secret)
auth.setToken(token, tokenSecret)
api
=
API(auth)
status
=
api.update_status(status
=
'搞定收工~'
)
|
这个时候,我们可以重构一下代码,写一个weibo类,来实现以上的功能,并且实现一些api的操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
class
weibo(
object
):
def
__init__(
self
):
self
.consumer_key
=
consumer_key
self
.consumer_secret
=
consumer_secret
def
getAtt(
self
, key):
try
:
return
self
.obj.__getattribute__(key)
except
Exception, e:
print
e
return
''
def
getAttValue(
self
, obj, key):
try
:
return
obj.__getattribute__(key)
except
Exception, e:
print
e
return
''
def
auth(
self
):
self
.auth
=
OAuthHandler(
self
.consumer_key,
self
.consumer_secret)
auth_url
=
self
.auth.get_authorization_url()
print
'Please authorize: '
+
auth_url
verifier
=
raw_input
(
'PIN: '
).strip()
self
.auth.get_access_token(verifier)
self
.api
=
API(
self
.auth)
def
setToken(
self
, token, tokenSecret):
self
.auth
=
OAuthHandler(
self
.consumer_key,
self
.consumer_secret)
self
.auth.setToken(token, tokenSecret)
self
.api
=
API(
self
.auth)
def
update(
self
, message):
message
=
message.encode(
"utf-8"
)
status
=
self
.api.update_status(status
=
message)
self
.obj
=
status
id
=
self
.getAtt(
"id"
)
return
id
def
destroy_status(
self
,
id
):
status
=
self
.api.destroy_status(
id
)
self
.obj
=
status
id
=
self
.getAtt(
"id"
)
return
id
def
comment(
self
,
id
, message):
comment
=
self
.api.comment(
id
=
id
, comment
=
message)
self
.obj
=
comment
mid
=
self
.getAtt(
"id"
)
return
mid
def
comment_destroy (
self
, mid):
comment
=
self
.api.comment_destroy(mid)
self
.obj
=
comment
mid
=
self
.getAtt(
"id"
)
text
=
self
.getAtt(
"text"
)
return
mid
def
repost(
self
,
id
, message):
post
=
self
.api.repost(
id
=
id
, status
=
message)
self
.obj
=
post
mid
=
self
.getAtt(
"id"
)
return
mid
def
get_username(
self
):
if
getattr
(
self
,
'_username'
,
None
)
is
None
:
self
._username
=
self
.auth.get_username()
return
self
._username
|
不知道读者还记得我们上面授权部分的代码。在login_check方法代码里,有这样一句话。
1
|
request.session[
'oauth_access_token'
]
=
access_token
|
授权用户的access_token已经保存在session变量中。因此,在用户授权完成时,我们就可以直接使用保存在session中的access_token,像这样:
1
2
3
4
5
|
access_token
=
request.session.get(
'oauth_access_token'
,
None
)
if
access_token
is
not
None
:
weibo_client
=
weibo()
weibo_client.setToken(access_token.key, access_token.secret)
weibo_client.update(
'全部完成~'
)
|
以上的例子中只使用了部分API,完整的API手册参考这里。
最后,本文参考两篇文章:《django接入新浪微博OAuth》,以及《新浪微博API开发简介之Python篇》