研究网易微博API - 2

2010-05-02 23:09

前几天经freestyler介绍, 从Tux那儿拿到了一份网易微博API的文档. 然后用python实现了一遍, 具体的代码现在还没正式发布, 只是放在的google code上: http://code.google.com/p/163microblog/. 关于网易微博API, 首先现在还在紧张开发中, 所以现在放出来的实现都是非官方的. 其次, 网易微博API很多地方参考了Twitter的API, 再次, 很多时候像我上一篇文章所讲的, 直接分析HTTP通讯也能给出一份可能不完全的API来...

今天早上无聊用python和已经写好的python的API实现写了一个客户端起来. 代码可参考: http://163microblog.googlecode.com/files/163microblog-cli.tar.gz

下面简单记录下开发过程.

设计

偶想做的东西是一个命令行下能够访问微博的工具, 能够看见自己的timeline, 能够发推就可以了. 不需要复杂的功能. 这种东西不需要什么前期设计, 从头开始往下写就是了...

登录和loop

用raw_input拿到用户名和密码, 偶写的API部分, 主类的实例化完成就已经完成了登录的过程.

username = raw_input('Please enter your username: ')
password = raw_input('Please enter your password: ')
usersession = Session(username, password)

返回usersession后, 你可以随意地调用网易微博的API了, 具体每个API是干嘛的, 偶希望偶写的注释已经比较详细了...

接下来, 偶们写一个死循环来接收用户输入和响应.

while True:
cmd = raw_input('Please enter your command: ')
if cmd == 'home':
home(usersession)
elif cmd == 'post':
text = raw_input('Please enter your status: ')
post(usersession, text)
elif cmd == 'quit' or cmd == 'exit':
print "    Bye~"
break
else:
help()

一开头就提示用户输入命令, 然后等, 用户输了命令就执行, 然后继续等...

用户的timeline

这个在网页上就是显示你的首页啦. 先放代码吧:

def home(session):
"""
    Display one's timeline.
    """
statuses = session.home_timeline(count=8)
for status in statuses:
print "%(text)s - %(user)s - %(time)sn" % {
'text': parse_text(status.text),
'user': colored(status.user.name, 'green'),
'time': colored(parse_time(status.created_at), 'red'),
}

用session.home_timeline()拿了8条微博, 因为默认的30条太多了... 接下来就是要让这个东西能够比较漂亮地显示出来. 我们要显示的内容应该包括推的内容, 发推时间和作者. 为了让这些东西能够区分开来, 偶想到了用ASCII颜色. 顺手一搜, 找到一个pypi里的包能够干这个事情, 链接是: termcolor. 偶把这个拿过来, 放在目录下就直接用了. 反正这个软件偶没改动, 而且也不打算改动, 它发布的协议和偶发布的网易微博API的协议都是一样的. 这个东西用起来还是挺省心的, 像上面代码中那样用一个colored()就可以了.

接下来解释下代码中status和status.user是什么东西. 这两个是偶定义两个类, 一个是Status, 一个是T163UserBase, 具体定义在微博API的models.py文件中. 定义这两个类是为了更方便地处理网易微博返回的json文件的格式. Status这个类对应你在网页上看到的一条推, 而T163UserBase对应一个用户的基本信息. 这个类通过继承能够用来放登录用户本人的个人信息, 也能够用来放关注者和被关注者的信息. 一条推肯定有一个作者, 这个作者就是一个用户, 因此每条推实例化的时候都会和一个用户的实例关联起来, 这就是为啥status这个Status的实例有一个T163UserBase的实例.

了解了这个, 后面的打印就没什么好讲的了. 写个循环, 依次将推的内容, 推的作者, 发推的时间打印出来就行了. 好吧, 这儿还稍复杂了点, 推里面的一些符号, 例如大于号(>, &gt;)和小于号(<, &lt;)被转义了, 偶要把这个转回去, 所以写了一个parsed_text函数(好吧, 实际上是抄的...). 另外, 偶的Status实例里的时间是UTC的, 偶要按照用户的时区把它转回来. 想了一个很山寨的办法写了个parse_time函数来干这件事.

发推

发推是用update这个函数来实现的, 代码如下:

def post(session, text):
"""
    Post a new status to t.163.com
    """
status = session.update(text)
if isinstance(status, Status):
print "done~ Refreshing..."
home(session)
else:
print "Something went wrong..."

按照API的说明, 用session.update()函数后, 服务器端应该返回发出的推的相关信息, 正好用来实例化一个Status. 所以偶的python实现也是将服务器返回的json文件解析后丢给Status. 因此, 如果这儿的status是一个Status实例, 那么偶们的推就成功地发出去了. 偶在这儿写了一个自动刷新. 调用刚才的home函数来显示更新后的用户的timeline.

登录优化

之前的登录很傻, 每次都需要用户输入用户名和密码, 偶优化了下这部分, 如果发现一个貌似cookie的东西, 就尝试用这个cookie来登录, 如果成功, 就不找用户要密码了. 这样更人性化一点~

from os.path import isfile

def main():
username = raw_input('Please enter your username:')
if isfile("%s.txt" % username):
try:
usersession = Session(username)
except RuntimeError:
password = raw_input('Please enter your password:')
usersession = Session(username, password)
else:
password = raw_input('Please enter your password:')
usersession = Session(username, password)

为了实现这一点, 偶还修改了API部分的相关代码, 去掉了Session类实例化部分对password的要求. 不过判断登录是否成功的部分代码还很山寨, 还需要修改.

当然偶们也可以写得更人性化一点, 如果发现一个疑似cookie的东西就先试试, 这样和web的用户体验就很相似了, 不过偶懒... 反正偶打字还算快, 不管了...