您的位置:首页 > 编程语言 > Python开发

python实现的douban.fm客户端,添加登录功能

2013-01-15 00:18 609 查看
一个月前心血来潮用python实现了一个简单的douban.fm客户端,计划是陆续将其完善成为Ubuntu下可替代web版本的douban.fm客户端。但后来因为事多,被一直搁着,没有再继续完善。就在昨天,一位园友在评论中提到了登录的实现,虽然最近依然事多,但突然很想实现这个功能。正好,前几天因为一些需要,曾用python实现过网站登录,约摸估计这douban.fm的登录不会差太多。

关于网站身份验证

http协议被设计为无连接协议,但现实中,很多网站需要对用户进行身份识别,cookie就是为此而诞生的。当我们用浏览器浏览网站时,浏览器会帮我们透明的处理cookie。而我们现在要第三方登录网站,这就必须对cookie的工作流程有一定的了解。

另外,很多网站为了防止程序自动登录而使用了验证码机制,验证码的介入会使登录过程变得麻烦,但也还不算太难处理。

实际中douban.fm的登录流程

为了模拟一个干净(不使用已有cookie)的登录流程,我使用chromium的隐身模式。

View Code

#!/usr/bin/python
# coding: utf-8

import sys
import os
import subprocess
import getopt
import time
import json
import urllib
import urllib2
import getpass
import ConfigParser
from cookielib import CookieJar

# 保存到文件
def save(filename, content):
file = open(filename, 'wb')
file.write(content)
file.close()

# 获取播放列表
def getPlayList(channel='0', opener=None):
url = 'http://douban.fm/j/mine/playlist?type=n&channel=' + channel
if opener == None:
return json.loads(urllib.urlopen(url).read())
else:
return json.loads(opener.open(urllib2.Request(url)).read())

# 发送桌面通知
def notifySend(picture, title, content):
subprocess.call([
'notify-send',
'-i',
os.getcwd() + '/' + picture,
title,
content])

# 登录douban.fm
def login(username, password):
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(CookieJar()))
while True:
print '正在获取验证码……'
captcha_id = opener.open(urllib2.Request(
'http://douban.fm/j/new_captcha')).read().strip('"')
save(
'验证码.jpg',
opener.open(urllib2.Request(
'http://douban.fm/misc/captcha?size=m&id=' + captcha_id
)).read())
captcha = raw_input('验证码: ')
print '正在登录……'
response = json.loads(opener.open(
urllib2.Request('http://douban.fm/j/login'),
urllib.urlencode({
'source': 'radio',
'alias': username,
'form_password': password,
'captcha_solution': captcha,
'captcha_id': captcha_id,
'task': 'sync_channel_list'})).read())
if 'err_msg' in response.keys():
print response['err_msg']
else:
print '登录成功'
return opener

# 播放douban.fm
def play(channel='0', opener=None):
while True:
if opener == None:
playlist = getPlayList(channel)
else:
playlist = getPlayList(channel, opener)

if playlist['song'] == []:
print '获取播放列表失败'
break
picture,

for song in playlist['song']:
picture = 'picture/' + song['picture'].split('/')[-1]

# 下载专辑封面
save(
picture,
urllib.urlopen(song['picture']).read())

# 发送桌面通知
notifySend(
picture,
song['title'],
song['artist'] + '\n' + song['albumtitle'])

# 播放
player = subprocess.Popen(['mplayer', song['url']])
time.sleep(song['length'])
player.kill()

def main(argv):
# 默认参数
channel = '0'
user = ''
password = ''

# 获取、解析命令行参数
try:
opts, args = getopt.getopt(
argv, 'u:p:c:', ['user=', 'password=', 'channel='])
except getopt.GetoptError as error:
print str(error)
sys.exit(1)

# 命令行参数处理
for opt, arg in opts:
if opt in ('-u', '--user='):
user = arg
elif opt in ('-p', '--password='):
password = arg
elif opt in ('-c', '--channel='):
channel = arg

if user == '':
play(channel)
else:
if password == '':
password = getpass.getpass('密码:')
opener = login(user, password)
play(channel, opener)

if __name__ == '__main__':
main(sys.argv[1:])


以下是本人使用自己的帐号登录并播放红心兆赫:





接下来,我会继续完善这个python douban.fm客户端程序,添加频道搜索和查看,全局按键控制等功能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: