python调用新浪微博API项目实践


Posted in Python onJuly 28, 2014

因为最近接触到调用新浪微博开放接口的项目,所以就想试试用python调用微博API。

SDK下载地址:http://open.weibo.com/wiki/SDK 代码不多十几K,完全可以看懂。

有微博账号可以新建一个APP,然后就可以得到app key和app secret,这个是APP获得OAuth2.0授权所必须的。

了解OAuth2可以查看链接新浪微博的说明。 OAuth2授权参数除了需要app key和app secret还需要网站回调地址redirect_uri,并且这个回调地址不允许是局域网的(神马localhost,127.0.0.1好像都不行),这个着实让我着急了半天。我使用API也不是网站调用,于是查了很多。看到有人写可以用这个地址替代,https://api.weibo.com/oauth2/default.html,我试了一下果然可以,对于?潘坷此凳歉龊孟?ⅰ?/p>

下面先来个简单的程序,感受一下:

设置好以下参数

import sys
import weibo
import webbrowser

APP_KEY = ''
MY_APP_SECRET = ''
REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html'

获得微博授权URL,如第2行,用默认浏览器打开后会要求登陆微博,用需要授权的账号登陆,如下图

api = weibo.APIClient(app_key=APP_KEY,app_secret=MY_APP_SECRET,redirect_uri=REDIRECT_URL)
authorize_url = api.get_authorize_url()
print(authorize_url)
webbrowser.open_new(authorize_url)

python调用新浪微博API项目实践

登陆后会调转到一个连接https://api.weibo.com/oauth2/default.html?code=92cc6accecfb5b2176adf58f4c

关键就是code值,这个是认证的关键。手动输入code值模拟认证

request = api.request_access_token(code, REDIRECT_URL)
access_token = request.access_token
expires_in = request.expires_in
api.set_access_token(access_token, expires_in)
api.statuses.update.post(status=u'Test OAuth 2.0 Send a Weibo!')

access_token就是获得的token,expires_in是授权的过期时间 (UNIX时间)

用set_access_token保存授权。往下就可以调用微博接口了。测试发了一条微博

python调用新浪微博API项目实践

但是这样的手动输入code方式,不适合程序的调用,是否可以不用打开链接的方式来请求登陆获取授权,经多方查找和参考,将程序改进如下,可以实现自动获取code并保存,方便程序服务调用。

accessWeibo

# -*- coding: utf-8 -*- 
#/usr/bin/env python 

#access to SinaWeibo By sinaweibopy 
#实现微博自动登录,token自动生成,保存及更新 
#适合于后端服务调用 


from weibo import APIClient 
import pymongo 
import sys, os, urllib, urllib2 
from http_helper import * 
from retry import * 
try: 
import json 
except ImportError: 
import simplejson as json 

# setting sys encoding to utf-8 
default_encoding = 'utf-8' 
if sys.getdefaultencoding() != default_encoding: 
reload(sys) 
sys.setdefaultencoding(default_encoding) 

# weibo api访问配置 
APP_KEY = '' # app key 
APP_SECRET = '' # app secret 
REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html' # callback url 授权回调页,与OAuth2.0 授权设置的一致 
USERID = '' # 登陆的微博用户名,必须是OAuth2.0 设置的测试账号 
USERPASSWD = '' # 用户密码 


client = APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=REDIRECT_URL) 

def make_access_token(): 
#请求access token 
params = urllib.urlencode({
'action':'submit',
'withOfficalFlag':'0',
'ticket':'',
'isLoginSina':'', 
'response_type':'code',
'regCallback':'',
'redirect_uri':REDIRECT_URL,
'client_id':APP_KEY,
'state':'',
'from':'',
'userId':USERID,
'passwd':USERPASSWD,
}) 

login_url = 'https://api.weibo.com/oauth2/authorize' 

url = client.get_authorize_url() 
content = urllib2.urlopen(url) 
if content: 
headers = { 'Referer' : url } 
request = urllib2.Request(login_url, params, headers) 
opener = get_opener(False) 
urllib2.install_opener(opener) 
try: 
f = opener.open(request) 
return_redirect_uri = f.url 
except urllib2.HTTPError, e: 
return_redirect_uri = e.geturl() 
# 取到返回的code 
code = return_redirect_uri.split('=')[1] 
#得到token 
token = client.request_access_token(code,REDIRECT_URL) 
save_access_token(token) 

def save_access_token(token): 
#将access token保存到MongoDB数据库
mongoCon=pymongo.Connection(host="127.0.0.1",port=27017)
db= mongoCon.weibo

t={
"access_token":token['access_token'],
"expires_in":str(token['expires_in']),
"date":time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
}
db.token.insert(t,safe=True) 

#Decorator 目的是当调用make_access_token()后再执行一次apply_access_token()
@retry(1) 
def apply_access_token(): 
#从MongoDB读取及设置access token 
try: 

mongoCon=pymongo.Connection(host="127.0.0.1",port=27017)
db= mongoCon.weibo
if db.token.count()>0:
tokenInfos=db.token.find().sort([("_id",pymongo.DESCENDING)]).limit(1)
else: 
make_access_token() 
return False 

for tokenInfo in tokenInfos:
access_token=tokenInfo["access_token"]
expires_in=tokenInfo["expires_in"]

try: 
client.set_access_token(access_token, expires_in) 
except StandardError, e: 
if hasattr(e, 'error'): 
if e.error == 'expired_token': 
# token过期重新生成 
make_access_token()
return False 
else: 
pass 
except: 
make_access_token()
return False 

return True 

if __name__ == "__main__": 
apply_access_token() 

# 以下为访问微博api的应用逻辑 
# 以发布文字微博接口为例
client.statuses.update.post(status='Test OAuth 2.0 Send a Weibo!')
retry.py

import math
import time

# Retry decorator with exponential backoff
def retry(tries, delay=1, backoff=2):
"""Retries a function or method until it returns True.

delay sets the initial delay, and backoff sets how much the delay should
lengthen after each failure. backoff must be greater than 1, or else it
isn't really a backoff. tries must be at least 0, and delay greater than
0."""

if backoff <= 1:
raise ValueError("backoff must be greater than 1")

tries = math.floor(tries)
if tries < 0:
raise ValueError("tries must be 0 or greater")

if delay <= 0:
raise ValueError("delay must be greater than 0")

def deco_retry(f):
def f_retry(*args, **kwargs):
mtries, mdelay = tries, delay # make mutable

rv = f(*args, **kwargs) # first attempt
while mtries > 0:
if rv == True or type(rv) == str: # Done on success ..
return rv

mtries -= 1 # consume an attempt
time.sleep(mdelay) # wait...
mdelay *= backoff # make future wait longer

rv = f(*args, **kwargs) # Try again

return False # Ran out of tries :-(

return f_retry # true decorator -> decorated function
return deco_retry # @retry(arg[, ...]) -> true decorator
http_helper.py

# -*- coding: utf-8 -*-
#/usr/bin/env python

import urllib2,cookielib

class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
def http_error_301(cls, req, fp, code, msg, headers):
result = urllib2.HTTPRedirectHandler.http_error_301(cls, req, fp, code, msg, headers)
result.status = code
print headers
return result

def http_error_302(cls, req, fp, code, msg, headers):
result = urllib2.HTTPRedirectHandler.http_error_302(cls, req, fp, code, msg, headers)
result.status = code
print headers
return result

def get_cookie():
cookies = cookielib.CookieJar()
return urllib2.HTTPCookieProcessor(cookies)

def get_opener(proxy=False):
rv=urllib2.build_opener(get_cookie(), SmartRedirectHandler())
rv.addheaders = [('User-agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)')]
return rv
Python 相关文章推荐
scrapy自定义pipeline类实现将采集数据保存到mongodb的方法
Apr 16 Python
python socket多线程通讯实例分析(聊天室)
Apr 06 Python
利用Python开发微信支付的注意事项
Aug 19 Python
pandas DataFrame 根据多列的值做判断,生成新的列值实例
May 18 Python
解决PyCharm的Python.exe已经停止工作的问题
Nov 29 Python
python批量从es取数据的方法(文档数超过10000)
Dec 27 Python
Python3安装Pillow与PIL的方法
Apr 03 Python
python之PyQt按钮右键菜单功能的实现代码
Aug 17 Python
python tkinter组件使用详解
Sep 16 Python
在notepad++中实现直接运行python代码
Dec 18 Python
Python模块_PyLibTiff读取tif文件的实例
Jan 13 Python
Python3+RIDE+RobotFramework自动化测试框架搭建过程详解
Sep 23 Python
python中的sort方法使用详解
Jul 25 #Python
python实现监控linux性能及进程消耗性能的方法
Jul 25 #Python
python的dict,set,list,tuple应用详解
Jul 24 #Python
Python常见数据结构详解
Jul 24 #Python
python海龟绘图实例教程
Jul 24 #Python
python实现绘制树枝简单示例
Jul 24 #Python
python实现进程间通信简单实例
Jul 23 #Python
You might like
PHP5中MVC结构学习
2006/10/09 PHP
使用YII2框架实现微信公众号中表单提交功能
2017/09/04 PHP
PHP让网站移动访问更加友好方法
2019/02/14 PHP
PHP保存Base64图片base64_decode的问题整理
2019/11/04 PHP
通过Unicode转义序列来加密,按你说的可以算是混淆吧
2007/05/06 Javascript
jQuery循环滚动展示代码 可应用到文字和图片上
2012/05/11 Javascript
node.js中的events.emitter.listeners方法使用说明
2014/12/10 Javascript
Javascript 计算字符串在localStorage中所占字节数
2015/10/21 Javascript
JavaScript获取客户端IP的方法(新方法)
2016/03/11 Javascript
Jquery中map函数的用法
2016/06/03 Javascript
移动端使用localStorage缓存Js和css文的方法(web开发)
2016/09/20 Javascript
基于vue2.0+vuex+localStorage开发的本地记事本示例
2017/02/28 Javascript
详解webpack 入门总结和实践(按需异步加载,css单独打包,生成多个入口文件)
2017/06/20 Javascript
webpack手动配置React开发环境的步骤
2018/07/02 Javascript
解决vue-cli单页面手机应用input点击手机端虚拟键盘弹出盖住input问题
2018/08/25 Javascript
javascript异步处理与Jquery deferred对象用法总结
2019/06/04 jQuery
python求素数示例分享
2014/02/16 Python
在Python的struct模块中进行数据格式转换的方法
2015/06/17 Python
Python的math模块中的常用数学函数整理
2016/02/04 Python
Python中一行和多行import模块问题
2018/04/01 Python
python3学习之Splash的安装与实例教程
2018/07/09 Python
Python中关键字global和nonlocal的区别详解
2018/09/03 Python
PyQt5通信机制 信号与槽详解
2019/08/07 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
Django框架中间件定义与使用方法案例分析
2019/11/28 Python
Windows 平台做 Python 开发的最佳组合(推荐)
2020/07/27 Python
蒙蒂塞罗商店:Monticello Shop
2018/11/25 全球购物
C/C++程序员常见面试题二
2015/11/19 面试题
银行服务明星推荐材料
2014/05/29 职场文书
学校食品安全实施方案
2014/06/14 职场文书
四风问题对照检查材料
2014/09/22 职场文书
工作检讨书范文
2015/01/23 职场文书
2015大学迎新晚会策划书
2015/07/16 职场文书
2016年学校党支部创先争优活动总结
2016/04/05 职场文书
Django给表单添加honeypot验证增加安全性
2021/05/06 Python
Jupyter notebook 不自动弹出网页的解决方案
2021/05/21 Python