Django开发中整合新浪微博API
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。如下:
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文件。代码:
#!/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,完成授权""" # http://mk2.com/?oauth_token=c30fa6d693ae9c23dd0982dae6a1c5f9&oauth_verifier=603896 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来说,我们就可以照着这么写:
# -*- 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对象了:
# -*- 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的操作。
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方法代码里,有这样一句话。
request.session['oauth_access_token'] = access_token
授权用户的access_token已经保存在session变量中。因此,在用户授权完成时,我们就可以直接使用保存在session中的access_token,像这样:
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篇》
不错哦~~这个很赞~~~特别是把东西共享到其他社交网站去。未来就应该是在WOW上喊一声,微博上就能看到开团信息,并且看到哪个人的facebook亮着缺没有上游戏
恩,对的对的,以后大家都是平台,实现各平台互通才是硬道理~
login_backurl = request.build_absolute_uri('/login_check')
url 设置那是logincheck
被误导了!
额,银哥...确实是当时我疏忽了,应该是login_backurl = request.build_absolute_uri('/logincheck')的
我查看了一下我的代码里是对的,当时写到blog里不晓得怎么就错了,改正了^^
嘿嘿,提醒一下后面看的人而已
很有感触,因为正在做这个,能问下通过授权后怎样获取当前登录用户的帐号,就是登录的帐号
你是指用户的信息么,你可以看这个接口:users/show 获取用户信息。具体的可以参考API文档。
我在搞这个的时候不知为什么,不能回调login_check,还有你们上面讨论的login_backurl = request.build_absolute_uri('/logincheck') 这个logincheck是干嘛的,求指点。。。
建议你去阅读一下OAuth的授权机制,页面:http://open.weibo.com/wiki/Oauth
首先要获取request token,用后定向到授权页,用户授权后,应用会拿到access token,凭借access token和secret,你的应用就有权进行一些操作。
login是获取request token的过程,接着定向到授权页,授权后定向到logincheck,来保存access token。然后定向到最初的页面。
大致是这样。
pin码那个页面可以打开,但是不知为什么跳不到授权的页面。。
报错呢?日志呢?查看错误原因丫
copy上面的代码完全没有问题啊,这个blog就是这个代码。
http://localhost/logincheck?oauth_token=c30fa6d693ae9c..............就这个页面无解。。。 我不知道这个logincheck跟login_check()有关系么。。不懂。。我菜鸟。。
url(r'^logincheck/$', 'login_check', name='logcheck')
在urls里有设定啊,logincheck/就映射到views中的login_check方法呀
晕, 忘这茬了,搞定了,谢拉~
学习了,今晚试试
weibo类放在django中哪里啊?我新手不太懂
Weibo类放在哪里看你具体需求呀,这边的调用什么的都在一个文件里
我做个论坛,想发帖的同时就能同步新浪微博,怎样实现呢?求解答?
你的论坛是Django的么,或者是Python的么?
同步发送就是帖子提交的时候调用新浪微博API来发送微博就可以了。
对啊,我论坛是LBforum,用django开发的
应该有plugin机制的吧,有没有人写过插件;或者hack一下代码,反正是open source的。
请教一下,django后台新增一篇文章怎么同步发布一条微博消息呢?怎么获取这个新增了文章的事件?
有两种解决方法。
比较原始的,但是比较耦合的是直接覆写Model的save方法,在保存后调用同步发送的代码。
第二种方法是使用Django中的signal,注册Model的post_save的信号接收函数,并在当中写同步代码。
效果上没什么区别,只是代码的形式不同。
博主您好:我在callback_uri里面写了127.0.0.1:8000,新浪服务器那边是说有错误的,我改成真实的域名之后又可以使用,我怎么才能做到在本地进行测试呢?
不能设成localhost的,要debug的话,改hosts文件。
重修改了hosts,可以了 =。=
你好 请问一下实在accounts下做吗? 我不知道将这些代码放在哪个目录下
可以参考我的博客的代码:https://bitbucket.org/chineking/chineblog/wiki/Home
不胜感激
给作者留言
关于作者
残阳似血(@秦续业),程序猿一枚,把梦想揣进口袋的挨踢工作者。现加入阿里云,研究僧毕业于上海交通大学软件学院ADC实验室。熟悉分布式数据分析(DataFrame并行化框架)、基于图模型的分布式数据库和并行计算、Dpark/Spark以及Python web开发(Django、tornado)等。
博客分类
搜索
点击排行
标签云
扫描访问
主题
残阳似血的微博
登录
最新评论
yosong 在文章“Django mptt介绍以及使用”下评论
。
yosong 在文章“Django mptt介绍以及使用”下评论
这个多级评论咋做呀,啊啊啊啊啊啊
热搜 在文章“PyOdps 0.4版本发布,从一个故事说起”下评论
文章不错交个朋友
啊啊 在文章“Django mptt介绍以及使用”下评论
console.log('helloworld')
admin22 在文章“Django mptt介绍以及使用”下评论
111111
关于作者
残阳似血(@秦续业),程序猿一枚,把梦想揣进口袋的挨踢工作者。现加入阿里云,研究僧毕业于上海交通大学软件学院ADC实验室。熟悉分布式数据分析(DataFrame并行化框架)、基于图模型的分布式数据库和并行计算、Dpark/Spark以及Python web开发(Django、tornado)等。
所有分类
友情链接
联系信息
地址
上海闵行区东川路800号
上海交通大学
200240
Mail
chinekingseu@gmail.com
QQ
344861256