网站调用新浪微博内容(试试用python调用微博API的SDK授权所必须的 )
优采云 发布时间: 2021-09-03 12:06网站调用新浪微博内容(试试用python调用微博API的SDK授权所必须的
)
因为最近接触到调用新浪微博开放接口的项目,想尝试用python调用微博API。
SDK下载链接:代码不超过十几K,完全可以理解。
如果你有微博账号,你可以创建一个应用,然后你就可以得到应用密钥和应用秘钥。这是应用获得 OAuth2.0 授权所必需的。
要了解OAuth2,可以查看新浪微博链接的说明。除了app key和app secret外,OAuth2授权参数还需要网站回调地址redirect_uri,而且这个回调地址不允许在局域网内(什么是localhost,127.0.0.1 好像不行),这个真的让我着急了好久。我没有使用API调用网站,所以我查了很多。看到有人写可以用这个地址代替,我试了一下,没问题,这对Diosi来说是个好消息。
我们先来一个简单的程序来感受一下:
设置以下参数
import sys
import weibo
import webbrowser
APP_KEY = ''
MY_APP_SECRET = ''
REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html'
获取微博授权网址,如第二行,用默认浏览器打开后,会要求登录微博,用需要授权的账号登录,如下图<//p
pprespan style="color: rgba(0, 128, 128, 1)"1/span api = weibo.APIClient(app_key=APP_KEY,app_secret=MY_APP_SECRET,redirect_uri=span style="color: rgba(0, 0, 0, 1)"REDIRECT_URL)
/spanspan style="color: rgba(0, 128, 128, 1)"2/span authorize_url =span style="color: rgba(0, 0, 0, 1)" api.get_authorize_url()
/spanspan style="color: rgba(0, 128, 128, 1)"3/span span style="color: rgba(0, 0, 255, 1)"print/spanspan style="color: rgba(0, 0, 0, 1)"(authorize_url)
/spanspan style="color: rgba(0, 128, 128, 1)"4/span webbrowser.open_new(authorize_url)/pre/p
pimg src='https://images0.cnblogs.com/blog/515896/201304/27174320-95b2c8e5fbaa430581575652dc9cabce.jpg' alt=''//p
p登录后会转成一个连接代码=92cc6accecfb5b2176adf58f4c/p
pkey是code值,是认证的关键。手动输入code值模拟认证/p
pprespan style="color: rgba(0, 128, 128, 1)"1/span request =span style="color: rgba(0, 0, 0, 1)" api.request_access_token(code, REDIRECT_URL)
/spanspan style="color: rgba(0, 128, 128, 1)"2/span access_token =span style="color: rgba(0, 0, 0, 1)" request.access_token
/spanspan style="color: rgba(0, 128, 128, 1)"3/span expires_in =span style="color: rgba(0, 0, 0, 1)" request.expires_in
/spanspan style="color: rgba(0, 128, 128, 1)"4/span span style="color: rgba(0, 0, 0, 1)"api.set_access_token(access_token, expires_in)
/spanspan style="color: rgba(0, 128, 128, 1)"5/span api.statuses.update.post(status=uspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"Test OAuth 2.0 Send a Weibo!/spanspan style="color: rgba(128, 0, 0, 1)"'/span)/pre/p
pprespan style="font-size: 15px"access_token就是获得的token,expires_in是授权的过期时间/span span style="font-size: 15px"(UNIX时间)
/span/pre/p
pprespan style="font-size: 15px"用set_access_token保存授权。往下就可以调用微博接口了。测试发了一条微博
/span/pre/p
pimg src='https://images0.cnblogs.com/blog/515896/201304/28100233-96d97f1c16e14d11a07cc59330996baa.jpg' alt=''//p
p但是,这样的手动代码输入方式并不适合调用程序。是否可以在不打开链接的情况下请求登录并获得授权?经过多方搜索参考,对程序进行如下改进,可以自动获取并保存代码,方便程序服务调用。/p
pimg src='https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif' alt=''//p
pimg src='https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif' alt=''//p
p访问微博/p
pprespan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" -*- coding: utf-8 -*- /spanspan style="color: rgba(0, 128, 0, 1)"
#/spanspan style="color: rgba(0, 128, 0, 1)"/usr/bin/env python /span
span style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)"access to SinaWeibo By sinaweibopy /spanspan style="color: rgba(0, 128, 0, 1)"
#/spanspan style="color: rgba(0, 128, 0, 1)"实现微博自动登录,token自动生成,保存及更新 /spanspan style="color: rgba(0, 128, 0, 1)"
#/spanspan style="color: rgba(0, 128, 0, 1)"适合于后端服务调用 /span
span style="color: rgba(0, 0, 255, 1)"from/span weibo span style="color: rgba(0, 0, 255, 1)"import/spanspan style="color: rgba(0, 0, 0, 1)" APIClient
/spanspan style="color: rgba(0, 0, 255, 1)"import/spanspan style="color: rgba(0, 0, 0, 1)" pymongo
/spanspan style="color: rgba(0, 0, 255, 1)"import/spanspan style="color: rgba(0, 0, 0, 1)" sys, os, urllib, urllib2
/spanspan style="color: rgba(0, 0, 255, 1)"from/span http_helper span style="color: rgba(0, 0, 255, 1)"import/span *
span style="color: rgba(0, 0, 255, 1)"from/span retry span style="color: rgba(0, 0, 255, 1)"import/span *
span style="color: rgba(0, 0, 255, 1)"try/spanspan style="color: rgba(0, 0, 0, 1)":
/spanspan style="color: rgba(0, 0, 255, 1)"import/spanspan style="color: rgba(0, 0, 0, 1)" json
/spanspan style="color: rgba(0, 0, 255, 1)"except/spanspan style="color: rgba(0, 0, 0, 1)" ImportError:
/spanspan style="color: rgba(0, 0, 255, 1)"import/spanspan style="color: rgba(0, 0, 0, 1)" simplejson as json
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" setting sys encoding to utf-8 /span
default_encoding = span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"utf-8/spanspan style="color: rgba(128, 0, 0, 1)"'/span
span style="color: rgba(0, 0, 255, 1)"if/span sys.getdefaultencoding() !=span style="color: rgba(0, 0, 0, 1)" default_encoding:
reload(sys)
sys.setdefaultencoding(default_encoding)
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" weibo api访问配置 /span
APP_KEY = span style="color: rgba(128, 0, 0, 1)"''/span span style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" app key /span
APP_SECRET = span style="color: rgba(128, 0, 0, 1)"''/span span style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" app secret /span
REDIRECT_URL = span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"https://api.weibo.com/oauth2/default.html/spanspan style="color: rgba(128, 0, 0, 1)"'/span span style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" callback url 授权回调页,与OAuth2.0 授权设置的一致 /span
USERID = span style="color: rgba(128, 0, 0, 1)"''/span span style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" 登陆的微博用户名,必须是OAuth2.0 设置的测试账号 /span
USERPASSWD = span style="color: rgba(128, 0, 0, 1)"''/span span style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" 用户密码 /span
span style="color: rgba(0, 0, 0, 1)"
client /span= APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=span style="color: rgba(0, 0, 0, 1)"REDIRECT_URL)
/spanspan style="color: rgba(0, 0, 255, 1)"def/spanspan style="color: rgba(0, 0, 0, 1)" make_access_token():
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)"请求access token /span
params =span style="color: rgba(0, 0, 0, 1)" urllib.urlencode({
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"action/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"submit/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"withOfficalFlag/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"0/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"ticket/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"''/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"isLoginSina/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"''/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"response_type/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"code/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"regCallback/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"''/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"redirect_uri/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)":REDIRECT_URL,
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"client_id/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)":APP_KEY,
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"state/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"''/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"from/spanspan style="color: rgba(128, 0, 0, 1)"'/span:span style="color: rgba(128, 0, 0, 1)"''/spanspan style="color: rgba(0, 0, 0, 1)",
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"userId/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)":USERID,
/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"passwd/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)":USERPASSWD,
})
login_url /span= span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"https://api.weibo.com/oauth2/authorize/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)"
url /span=span style="color: rgba(0, 0, 0, 1)" client.get_authorize_url()
content /span=span style="color: rgba(0, 0, 0, 1)" urllib2.urlopen(url)
/spanspan style="color: rgba(0, 0, 255, 1)"if/spanspan style="color: rgba(0, 0, 0, 1)" content:
headers /span= { span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"Referer/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)" : url }
request /span=span style="color: rgba(0, 0, 0, 1)" urllib2.Request(login_url, params, headers)
opener /span=span style="color: rgba(0, 0, 0, 1)" get_opener(False)
urllib2.install_opener(opener)
/spanspan style="color: rgba(0, 0, 255, 1)"try/spanspan style="color: rgba(0, 0, 0, 1)":
f /span=span style="color: rgba(0, 0, 0, 1)" opener.open(request)
return_redirect_uri /span=span style="color: rgba(0, 0, 0, 1)" f.url
/spanspan style="color: rgba(0, 0, 255, 1)"except/spanspan style="color: rgba(0, 0, 0, 1)" urllib2.HTTPError, e:
return_redirect_uri /span=span style="color: rgba(0, 0, 0, 1)" e.geturl()
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)" 取到返回的code /span
code = return_redirect_uri.split(span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"=/spanspan style="color: rgba(128, 0, 0, 1)"'/span)[1span style="color: rgba(0, 0, 0, 1)"]
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)"得到token /span
token =span style="color: rgba(0, 0, 0, 1)" client.request_access_token(code,REDIRECT_URL)
save_access_token(token)
/spanspan style="color: rgba(0, 0, 255, 1)"def/spanspan style="color: rgba(0, 0, 0, 1)" save_access_token(token):
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)"将access token保存到MongoDB数据库/span
mongoCon=pymongo.Connection(host=span style="color: rgba(128, 0, 0, 1)""/spanspan style="color: rgba(128, 0, 0, 1)"127.0.0.1/spanspan style="color: rgba(128, 0, 0, 1)""/span,port=27017span style="color: rgba(0, 0, 0, 1)")
db/span=span style="color: rgba(0, 0, 0, 1)" mongoCon.weibo
t/span=span style="color: rgba(0, 0, 0, 1)"{
/spanspan style="color: rgba(128, 0, 0, 1)""/spanspan style="color: rgba(128, 0, 0, 1)"access_token/spanspan style="color: rgba(128, 0, 0, 1)""/span:token[span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"access_token/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)"],
/spanspan style="color: rgba(128, 0, 0, 1)""/spanspan style="color: rgba(128, 0, 0, 1)"expires_in/spanspan style="color: rgba(128, 0, 0, 1)""/span:str(token[span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"expires_in/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)"]),
/spanspan style="color: rgba(128, 0, 0, 1)""/spanspan style="color: rgba(128, 0, 0, 1)"date/spanspan style="color: rgba(128, 0, 0, 1)""/span:time.strftime(span style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(128, 0, 0, 1)"%Y-%m-%d %H:%M:%S/spanspan style="color: rgba(128, 0, 0, 1)"'/spanspan style="color: rgba(0, 0, 0, 1)",time.localtime(time.time()))
}
db.token.insert(t,safe/span=span style="color: rgba(0, 0, 0, 1)"True)
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)"Decorator 目的是当调用make_access_token()后再执行一次apply_access_token()/span
@retry(1span style="color: rgba(0, 0, 0, 1)")
/spanspan style="color: rgba(0, 0, 255, 1)"def/spanspan style="color: rgba(0, 0, 0, 1)" apply_access_token():
/spanspan style="color: rgba(0, 128, 0, 1)"#/spanspan style="color: rgba(0, 128, 0, 1)"从MongoDB读取及设置access token /span
span style="color: rgba(0, 0, 255, 1)"try/spanspan style="color: rgba(0, 0, 0, 1)":
mongoCon/span=pymongo.Connection(host=span style="color: rgba(128, 0, 0, 1)""/spanspan style="color: rgba(128, 0, 0, 1)"127.0.0.1/spanspan style="color: rgba(128, 0, 0, 1)""/span,port=27017span style="color: rgba(0, 0, 0, 1)")
db/span=span style="color: rgba(0, 0, 0, 1)" mongoCon.weibo
/spanspan style="color: rgba(0, 0, 255, 1)"if/span 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!')
重试.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 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