阳春面 | 关注互联网,Android

CAT | python

二/10

24

对yupoo api的python封装

对yupoo api的python封装,2007的时候写的了,
那时候写了用来在nokia s60手机上上传照片到yupoo,
也是第一次接触xmlrpc,rest方式的调用。

yupoo.py,对yupoo api的封装


#--------------------------------------------------------------------
# -*- coding: utf-8 -*-
# Name:        yupoo api for python
# Purpose:     yupoo api for python
#
# Author:      chenyc
# Created:     22-06-2007
# Copyright:   (c) chenyc 2007
# Licence:     GNU
#--------------------------------------------------------------------

import yupoo_helper,urllib,httplib,os
config=yupoo_helper.config
def login(username,password):
    opener=yupoo_helper.bulid_opener()
    login_url='http://www.yupoo.com/account/auth/'
    postdata=urllib.urlencode({'j_username':username,'j_password':password,'j_remember_me':'1'})
    opener.open(login_url,postdata)
    return opener

def user_auth(username,password,perms,frob):
    opener=login(username,password)
    auth_url='http://www.yupoo.com/services/auth/?'
    params={'api_key':config['api_key'],'frob':frob,'perms':perms}
    api_sig=yupoo_helper.sig(yupoo_helper.join_params(params))
    auth_url=auth_url+'api_key='+config['api_key']+'&frob='+frob+'&perms='+perms+'&api_sig='+api_sig
    opener.open(auth_url)

def auth_set_perms(username,password,perms):
    a=Auth()
    frob=a.auth_getFrob()['frob']
    user_auth(username,password,perms,frob)
    auth_info=a.auth_getToken(frob)
    config['auth_token']=auth_info['token']
    yupoo_helper.set_config(config)
    return auth_info

def auth_get_FullToken(mini_token):
    a=Auth()
    auth_info=a.auth_getFullToken(mini_token)
    config['auth_token']=auth_info['token']
    yupoo_helper.set_config(config)
    return auth_info

def auth_checkToken(auth_token):
    a=Auth()
    auth_info=a.auth_checkToken(auth_token)
    return auth_info

class Auth:
    def auth_getFrob(self):
        method_name='yupoo.auth.getFrob'
        params={}
        return  yupoo_helper.call_method(method_name,params,True)

    def auth_getToken(self,frob):
        method_name='yupoo.auth.getToken'
        params={'frob':frob}
        return  yupoo_helper.call_method(method_name,params,True)

    def auth_getFullToken(self,mini_token):
        method_name='yupoo.auth.getFullToken'
        params={'mini_token':mini_token}
        return yupoo_helper.call_method(method_name,params,True)

    def auth_checkToken(self,auth_token):
        method_name='yupoo.auth.checkToken'
        params={'auth_token':auth_token}
        return  yupoo_helper.call_method(method_name,params,True)

class YupooAPI:
    def __init__(self,api_key,shared_secret,username='',password='',perms='delete'):
        if config['api_key']== api_key and config['shared_secret']==shared_secret \
        and config['perms']==perms and config['auth_token']<>'?':
            auth_info=auth_checkToken(config['auth_token'])
        else:
            self.set_api_info(api_key,shared_secret,perms)
            auth_info=auth_set_perms(username,password,perms)
        self.auth_token=auth_info['token']
        self.user_id=auth_info['user']['id']
        self.callmethod=yupoo_helper.call_method

    def blogs_getList(self):
        method_name='yupoo.blogs.getList'
        params={}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def blogs_postPhoto(self,blog_id,photo_id,title,description,blog_password=''):
        method_name='yupoo.blogs.postPhoto'
        params={'blog_id':blog_id,'photo_id':photo_id,'title':title,
                'description':description}
        if blog_password<>'':
            paramsp['blog_password']=blog_password

        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def contacts_getList(self,filter=''):
        method_name='yupoo.contacts.getList'
        params={}
        if filter<>'':
            params={'filter':filter}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def contacts_getPublicList(self,user_id=''):
        if user_id=='':
            user_id=self.user_id
        method_name='yupoo.contacts.getPublicList'
        params={'user_id':user_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def favorites_add(self,photo_id):
        method_name='yupoo.favorites.add'
        params={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def favorites_getList(self,user_id='',per_page='100',page='1'):
        if user_id=='':
            user_id=self.user_id
        method_name='yupoo.favorites.getList'
        params={'per_page':per_page,'page':page}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def favorites_remove(self,photo_id):
        method_name='yupoo.favorites.remove'
        params={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def groups_getList(self):
        method_name='yupoo.groups.getList'
        params={}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def groups_pools_getContext(self,photo_id,group_id):
        method_name='yupoo.groups.pools.getContext'
        params={'photo_id':photo_id,'group_id':group_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def groups_pools_getPhotos(self,group_id,tags='',user_id='',per_page='100',page='1'):
        method_name='yupoo.groups.pools.getPhotos'
        params={'group_id':group_id,'per_page':per_page,'page':page}
        if user_id<>'':
            params['user_id']=user_id
        if user_id<>'':
            params['tags']=tags
        return  yupoo_helper.call_method(method_name,params)

    def people_findByEmail(self,email):
        method_name='yupoo.people.findByEmail'
        params={'email':email}
        return  yupoo_helper.call_method(method_name,params)

    def people_findByUsername(self,username):
        method_name='yupoo.people.findByUsername'
        params={'username':username}
        return  yupoo_helper.call_method(method_name,params)

    def people_getUploadStatus(self):
        method_name='yupoo.people.getUploadStatus'
        params={}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_addTags(self,photo_id,tags):
        method_name='yupoo.photos.addTags'
        params={'photo_id':photo_id,'tags':tags}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_delete(self,photo_id):
        method_name='yupoo.photos.delete'
        parmas={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_getContext(self,photo_id):
        method_name='yupoo.photos.getContext'
        parmas={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params)

    def photos_getArchives(self,user_id='',atype='posted'):
        method_name='yupoo.photos.getArchives'
        if user_id=='':
            user_id=self.user_id
        params={'user_id':user_id,'type':atype}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_getInfo(self,photo_id):
        method_name='yupoo.photos.getInfo'
        params={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params)

    def photos_getPerms(self,photo_id):
        method_name='yupoo.photos.getPerms'
        params={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_removeTag(self,photo_id,tag):
        method_name='yupoo.photos.removeTag'
        params={'photo_id':photo_id,'tag':tag}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_search(self,user_id='',tags='',text='',per_page='100',page='1'):
        method_name='yupoo.photos.search'
        if user_id=='':
            user_id=self.user_id
        params={'user_id':user_id,'tags':tags,'text':text,'per_page':per_page,'page':page}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_setMeta(self,photo_id,title,description=''):
        method_name='yupoo.photos.setMeta'
        params={'photo_id':photo_id,'title':title,'description':description}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_setPerms(self,photo_id,view,comment,addmeta,blogthis,viewexif ):
        method_name='yupoo.photos.setPerms'
        params={'photo_id':photo_id,'view':view,'comment':comment,
                'addmeta':addmeta,'blogthis':blogthis,'viewexif':viewexif}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_setTags(self,photo_id,tags):
        method_name='yupoo.photos.setTags'
        params={'photo_id':photo_id,'tags':tags}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_licenses_getInfo(self):
        method_name='yupoo.photos.licenses.getInfo'
        params={}
        return  yupoo_helper.call_method(method_name,params)

    def photos_licenses_setLicense(self,photo_id,license_id):
        method_name='yupoo.photos.licenses.setLicense'
        params={'photo_id':photo_id,'license_id':license_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_notes_add(self,photo_id,note_x,note_y,note_w,note_h,note_text):
        method_name='yupoo.photos.notes.add'
        params={'photo_id':photo_id,'note_x':note_x,'note_y':note_y,
                'note_w':note_w,'note_h':note_h,'note_text':note_text}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_notes_delete(self,note_id):
        method_name='yupoo.photos.notes.delete'
        params={'note_id':note_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_notes_edit(self,note_id,note_x,note_y,note_w,note_h,note_text):
        method_name='yupoo.photos.notes.edit'
        params={'note_id':note_id,'note_x':note_x,'note_y':note_y,
                'note_w':note_w,'note_h':note_h,'note_text':note_text}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def photos_notes_getList(self,photo_id):
        method_name='yupoo.photos.notes.getList'
        params={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params)

    def albums_addPhoto(self,album_id,photo_id):
        method_name='yupoo.albums.addPhoto'
        params={'album_id':album_id,'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def albums_create(self,title,description='',cover_id=''):
        method_name='yupoo.albums.create'
        params={'title':title,'description':description}
        if cover_id<>'':
            params['cover_id']=cover_id
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def albums_delete(self,album_id):
        method_name='yupoo.albums.delete'
        params={'album_id':album_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def albums_editMeta(self,album_id,title,description=''):
        method_name='yupoo.albums.editMeta'
        params={'album_id':album_id,'title':title,'description':description}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def albums_editPhotos(self,album_id,photo_ids,cover_id=''):
        method_name='yupoo.albums.editPhotos'
        params={'album_id':album_id,'photo_ids':photo_ids}
        if cover_id<>'':
           params['cover_id']=cover_id
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def albums_getContext(self,album_id,photo_id):
        method_name='yupoo.albums.getContext'
        params={'album_id':album_id,'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params)

    def albums_getList(self,user_id=''):
        if user_id=='':
            user_id=self.user_id
        method_name='yupoo.albums.getList'
        params={'user_id':user_id}
        return  yupoo_helper.call_method(method_name,params)

    def albums_getPhotos(self,album_id):
        method_name='yupoo.albums.getPhotos'
        params={'album_id':album_id}
        return  yupoo_helper.call_method(method_name,params)

    def albums_order(self,album_ids):
        method_name='yupoo.albums.order'
        params={'album_ids':album_ids}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def albums_removePhoto(self,album_id,photo_id):
        method_name='yupoo.albums.removePhoto'
        params={'album_id':album_id,'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params,True,self.auth_token)

    def tags_getListPhoto(self,photo_id):
        method_name='yupoo.tags.getListPhoto'
        params={'photo_id':photo_id}
        return  yupoo_helper.call_method(method_name,params)

    def tags_getListUser(self,user_id=''):
        if user_id=='':
            user_id=self.user_id
        method_name='yupoo.tags.getListUser'
        params={'user_id':user_id}
        return  yupoo_helper.call_method(method_name,params)

    def tags_getListUserPopular(self,user_id='',count='10'):
        if user_id=='':
            user_id=self.user_id
        method_name='yupoo.tags.getListUserPopular'
        params={'user_id':user_id,'count':count}
        return  yupoo_helper.call_method(method_name,params)

    def tags_getRelated(self,tag):
        method_name='yupoo.tags.getRelated'
        params={'tag':tag}
        return  yupoo_helper.call_method(method_name,params)

    def set_api_info(self,api_key,shared_secret,perms=''):
        if api_key<>'':
            config['api_key']=api_key
        if shared_secret<>'':
            config['shared_secret']=shared_secret
        if perms<>'':
            config['perms']=perms
        yupoo_helper.set_config(config)

    def bulid_photo_url(self,host,adir,filename,size_type='',secret='',originalformat=''):
        if originalformat=='':
            url='http://photo'+host+'.yupoo.com/'+adir+'/'+filename+size_type+'.jpg'
        else:
            url='http://photo'+host+'.yupoo.com/'+adir+'/'+filename+'_'+secret+'.'+originalformat
        return url

    def upload_photo(self,photo,title='',description='',tags='',album_id='',group_id='',
                 is_public='1',is_contact='1',is_friend='1',is_family='1'):

        upload_url='http://www.yupoo.com/api/upload/'
        auth_token=config['auth_token']
        params={'api_key':config['api_key'],'title':title,'description':description,'tags':tags,
               'is_public':is_public,'is_contact':is_contact,
                'is_friend':is_friend,'is_family':is_family,'auth_token':auth_token}
        if album_id<>'':
            params['album_id']=album_id
        if group_id<>'':
            params['group_id']=group_id

        api_sig=yupoo_helper.sig(yupoo_helper.join_params(params))
        params['api_sig']=api_sig
        params['photo']=photo
        opener=yupoo_helper.build_Multipart_opener()
        return opener.open(upload_url,params).read()

if __name__ == "__main__":

    pass
    #p=people()
    #photo=pho.search( p.findByUsername('chenyangcun')['id'])
    #print bulid_photo_url(photo['host'],photo['dir'],photo['filename'])
    #p=people()
    #print p.getUploadStatus()

   # f=open('c:\\chenyc.jpg','rb')
   # print upload_photo(f)

yupoo_helper.py,读取用户相关的配置文件,返回xml的解析成dict处理

#----------------------------------------------------------------------
# -*- coding: utf-8 -*-
# Name:        yupoo_helper
# Purpose:
#
# Author:      chenyc
# Created:     22-06-2007
# Copyright:   (c) chenyc 2007
# Licence:     GNU
#-----------------------------------------------------------------------
import md5,urllib,httplib,os
import urllib2,MultipartPostHandler,cookielib
try:
    import xml.etree.ElementTree as ET  #python2.5
except ImportError:
    import elementtree.ElementTree as ET

def read_config():
    config={}
    keys=[u'api_key','shared_secret','mini_token','auth_token','perms']
    try:
        f=file('yupoo.xml','r')
        root=ET.parse(f)
        f.close()
    except:
        for key in keys:
            config[key]='?'
        root=set_config(config)
    db=bulid_dic(root)
    for key in keys:
        config[key]=db[key]
    return config

def set_config(config):
    root=ET.Element('XML')
    for key,value in config.items():
        key_node=ET.SubElement(root,key)
        key_node.text=value
    tree=ET.ElementTree(root)
    f=file('yupoo.xml','w')
    tree.write(f)
    f.close()
    return root

#解析yupoo返回的xml,并生成字典
def bulid_dic(root):
    dic={}
    iter = root.getiterator()
    for element in iter:
        if element.keys():
            key_dic={}
            for name,value in element.items():
                key_dic[name]=value
            if dic.has_key(element.tag):
                if type(dic[element.tag]) is list:
                    dic[element.tag].append(key_dic)
                else:
                    ll=[dic[element.tag],key_dic]
                    dic[element.tag]=ll
            else:
                dic[element.tag]=key_dic;
        else:
            dic[element.tag]=element.text
    return dic

#生成api_sgi
def sig(string):
    return md5.new(string).hexdigest()

def call_method(method_name,params,need_sig=False,auth_token=''):
    params['api_key']=config['api_key']
    if auth_token <>'':
        params['auth_token']=auth_token
    if need_sig:
        api_sig=sig(join_params(params,method_name))
        params['api_sig']=api_sig
    params['method']=method_name
    rest_url='http://www.yupoo.com/api/rest/?'
    for key,value in params.items():
        rest_url=rest_url+key+'='+value+'&'
        xmldata=urllib.urlopen(rest_url).read()
    if xmldata<>'':
        root=ET.fromstring(xmldata)
        return bulid_dic(root)
    else:
	return {}

def join_params(params,method_name=''):
    string=config['shared_secret']
    if method_name<>'':
        params['method']=method_name
    keys=params.keys()
    keys.sort()
    for k in keys:
        string=string+k+params[k]
    return string

#common method for yupoo api
#创建opener,用来登录验证
def bulid_opener():
    cj=cookielib.LWPCookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
    urllib2.install_opener(opener)
    opener.addheaders =[
        ("User-agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031107 Debian/1.5-3"),
        ("Accept", "text/html, image/jpeg, image/png, text/*, image/*, */*")]
    return opener

#创建Multipart opener,用来上传文件
def build_Multipart_opener():
    cookies = cookielib.CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies),
                                MultipartPostHandler.MultipartPostHandler)
    return opener

config=read_config()

MultipartPostHandler.py 作者:Will Holcomb,用来处理照片等附件的上传,不过这个在nokia s60的手机上不能调用成功,还需要修改一下。

#!/usr/bin/python

####
# 02/2006 Will Holcomb <wholcomb@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
"""
Usage:
  Enables the use of multipart/form-data for posting forms

Inspirations:
  Upload files in python:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306

  urllib2_file:
    Fabien Seisen: <fabien@seisen.org>

Example:
  import MultipartPostHandler, urllib2, cookielib

  cookies = cookielib.CookieJar()
  opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies),
                                MultipartPostHandler.MultipartPostHandler)
  params = { "username" : "bob", "password" : "riviera",
             "file" : open("filename", "rb") }
  opener.open("http://wwww.bobsite.com/upload/", params)

Further Example:
  The main function of this file is a sample which downloads a page and
  then uploads it to the W3C validator.
"""

import urllib
import urllib2
import mimetools, mimetypes
import os, stat

class Callable:
    def __init__(self, anycallable):
        self.__call__ = anycallable

# Controls how sequences are uncoded. If true, elements may be given multiple values by
#  assigning a sequence.
doseq = 1

class MultipartPostHandler(urllib2.BaseHandler):
    handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first

    def http_request(self, request):
        data = request.get_data()
        if data is not None and type(data) != str:
            v_files = []
            v_vars = []
            try:
                 for(key, value) in data.items():
                     if type(value) == file:
                         v_files.append((key, value))
                     else:
                         v_vars.append((key, value))
            except TypeError:
                systype, value, traceback = sys.exc_info()
                raise TypeError, "not a valid non-string sequence or mapping object", traceback

            if len(v_files) == 0:
                data = urllib.urlencode(v_vars, doseq)
            else:
                boundary, data = self.multipart_encode(v_vars, v_files)
                contenttype = 'multipart/form-data; boundary=%s' % boundary
                if(request.has_header('Content-Type')
                   and request.get_header('Content-Type').find('multipart/form-data') != 0):
                    print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
                request.add_unredirected_header('Content-Type', contenttype)

            request.add_data(data)
        return request

    def multipart_encode(vars, files, boundary = None, buffer = None):
        if boundary is None:
            boundary = mimetools.choose_boundary()
        if buffer is None:
            buffer = ''
        for(key, value) in vars:
            buffer += '--%s\r\n' % boundary
            buffer += 'Content-Disposition: form-data; name="%s"' % key
            buffer += '\r\n\r\n' + value + '\r\n'
        for(key, fd) in files:
            file_size = os.fstat(fd.fileno())[stat.ST_SIZE]
            filename = fd.name.split('/')[-1]
            contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
            buffer += '--%s\r\n' % boundary
            buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename)
            buffer += 'Content-Type: %s\r\n' % contenttype
            # buffer += 'Content-Length: %s\r\n' % file_size
            fd.seek(0)
            buffer += '\r\n' + fd.read() + '\r\n'
        buffer += '--%s--\r\n\r\n' % boundary
        return boundary, buffer
    multipart_encode = Callable(multipart_encode)

    https_request = http_request

def main():
    import tempfile, sys

    validatorURL = "http://validator.w3.org/check"
    opener = urllib2.build_opener(MultipartPostHandler)

    def validateFile(url):
        temp = tempfile.mkstemp(suffix=".html")
        os.write(temp[0], opener.open(url).read())
        params = { "ss" : "0",            # show source
                   "doctype" : "Inline",
                   "uploaded_file" : open(temp[1], "rb") }
        print opener.open(validatorURL, params).read()
        os.remove(temp[1])

    if len(sys.argv[1:]) > 0:
        for arg in sys.argv[1:]:
            validateFile(arg)
    else:
        validateFile("http://www.google.com")

if __name__=="__main__":
    main()

·

以前写的下载yahoo mp3的代码,不知道现在还能不能用;
yahoomp3类根据命令行输入的歌曲名,从chinamp3获取歌曲列表并打印到屏幕,
需要选择一个,然后会通过wget进行下载(wget在linux系统下默认都有的,windows下需要另外下载),歌曲下载完后,自动修改ID3标签,这个通过Ben Gertzfield写的ID3.py进行修改的。

downmp3.py


#! /usr/bin/python
# create by chenyc version:0.3

import re,urllib,os,socket,locale,sys,getopt,time,urllib2
import ID3
LOCALE_CODE=locale.getdefaultlocale()[1]
WEB_CODE='gbk'

'''DOWN MUSIC FILE FORM MP3.YAHOO.CN'''
class yahoomp3:
    def __init__(self,time_out=0.3,directory='./'):
        self.time_out=time_out
        if directory[-1]<>'/':
           directory=directory+'/'
        self.path=directory

    #analyse html,return result list
    def analyse_html(self,url,expression):
        socket.setdefaulttimeout(10)
        try:
            urldata=urllib.urlopen(url)
            html=urldata.read()
            re_list=re.findall(expression,html)
            return re_list
        except:
            print 'can''t connect to the yahoo website! '
            return 1

    #get the music file download url from the search url
    def get_down_url(self,search_url):
        expression='<a href="(.*)" onclick="return'
        music_url_list=self.analyse_html(search_url,expression)
        i=0
        while len(music_url_list)>0 and i<len(music_url_list) :
            expression='</b><a href="(.*)" target=_blank>'
            down_url_list=self.analyse_html(music_url_list[i],expression)
            if len (down_url_list)>0:
                down_url='http://'+urllib.quote(down_url_list[0][7:])
            print down_url
            try:
                socket.setdefaulttimeout(self.time_out)
                tmp=urllib.urlopen(down_url).readline()
                if  len(tmp) >1 and tmp.upper().find('<')==-1:
                    break
                else:
                    i=i+3
            except:
                i=i+3

        if i<len(music_url_list):
            return down_url

    #generate search url and call method 'down_file'
    def down_music(self,name,author='',file_type='all'):
        if author is  None:
            print 'the author not find in chinamp3,do you want to download anyway?'
            if str(raw_input('input y or n for continue:')).upper() <> 'Y':
                return 1
        else:
            author=author.decode(LOCALE_CODE).encode(WEB_CODE)

        name=name.decode(LOCALE_CODE).encode(WEB_CODE)
        name='_'.join(name.split())
        search_url='http://music.cn.yahoo.com/search?pid=ysearch&source=ysearch_music_result_topsearch&p='
        option='&mimetype='+file_type+'&size=3&source=ysearch_music_result_size_3'
        if author is not None:
            search_url=search_url+name+'+'+author+option
        else:
            search_url=search_url+name+'+'+option
        self.down_file(name,author,search_url)

    #use wget to download music file
    def down_file(self,music_name,author,search_url):
        file_path=self.path
        if author is not None:
            file_name=author+'_'+music_name
        else:
            file_name=music_name
        file_name=file_name.decode(WEB_CODE).encode(LOCALE_CODE)
        try:
            file_list=os.listdir(file_path)
        except:
            print 'list dir error,abort!'
            return 1

        for name in file_list:
            if name.split('.')[0]==file_name:
                print 'file '+file_name+' exit,ignore download!'
                return 1

        down_url=self.get_down_url(search_url)
        if down_url is not None:
            print 'down music '+file_name
            ext=down_url.split('.')[-1]
            file_name=file_name+'.'+ext
            exe_wgetstr='wget --timeout=30 -l 10 -O '+file_path+file_name+' '+down_url
            os.system(exe_wgetstr)
            change_ID3(file_path,file_name)
        else:
            print 'FILE NOT FOUND!'

'''GET MUSIC INFO FROM CHINAMP3.COM'''
class music_info:
    #return to post requst from chinamp3
    def get_html(self,url,postdata):
        urldata=urllib2.urlopen(url, postdata)
        html=urldata.read().decode(WEB_CODE).encode(LOCALE_CODE)
        p=re.compile('</div></td></tr>')
        html=p.sub('\n',html)
        return html

    #get author list from music name
    def get_author_list(self,name):
        name=name.decode(LOCALE_CODE).encode(WEB_CODE)
        value=2
        url='http://search.chinamp3.com/search/searchcontent.php'
        postdata=urllib.urlencode({'type':value,'key':name})
        html=self.get_html(url,postdata)
        exp='&singer_name=(.*)\'\)}">'
        author_list=re.findall(exp,html)
        return author_list

    #get music name list from author
    def get_music_name(self,author):
        author=author.decode(LOCALE_CODE).encode(WEB_CODE)
        value=1
        url='http://search.chinamp3.com/search/searchcontent.php'
        postdata=urllib.urlencode({'type':value,'key':author})
        html=self.get_html(url,postdata)
        exp='php\?song_name=(.*)&singer_name='
        music_list=re.findall(exp,html)
        return music_list

    #get lyrics form music name and author
    def get_lyrics(self,name,author):
        name=name.decode(LOCALE_CODE).encode(WEB_CODE)
        author=author.decode(LOCALE_CODE).encode(WEB_CODE)
        url='http://geci.chinamp3.com/relatedgeci.php?song_name='+name+'&singer_name='+author
        urldata=urllib.urlopen(url)
        html=urldata.read().decode(WEB_CODE).encode(LOCALE_CODE)
        p=re.compile('\s')
        html=p.sub('',html)
        exp='</font><br /><br />(.*)</div></td></tr><tr><td><divalign="center"><fontcolor="#FF0000">'
        lyrics_list=re.findall(exp,html)
        if len(lyrics_list)>0:
            lyrics=lyrics_list[0]
            p=re.compile('<br />|<br/>')
            lyrics=p.sub('\n',lyrics)
            return lyrics

#change the ID3
def change_ID3(file_path,file_name):
    mp3file=file_path+file_name
    try:
        id3info=ID3.ID3(mp3file)
    except:
        print 'open file error!'
        return 1
    mp3info=file_name.split('.')[0].split('_')
    if len(mp3info)==2:
        id3info['ARTIST']=mp3info[0]
        id3info['TITLE']=mp3info[1]
    elif len(mp3info)==1:
        id3info['TITLE']=mp3info[0]

#get author from name
def get_author(name):
    mp3info=music_info();
    author_list=mp3info.get_author_list(name)
    count=len(author_list)
    if count>1:
        print 'please select author from the list:'
        i=0
        for author in author_list:
            print str(i)+'.'+author
            i=i+1
        while True:
            try:
                select=int(raw_input('please select one author:'))
            except:
                continue
            if select<len(author_list):
                author=author_list[select]
                return author
            else:
                print "you select the worng num,please select again!"
                continue
    elif count==1:
        return author_list[0]

# the main method,pass music name and option to program
def main (argv):
    file_type='all'
    author=''
    name=''
    directory='./'
    time_out=0.3
    try:
        opts,args = getopt.getopt (argv, "ha:t:d:o:", ["help","author=","type=","directory=","time out="])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    for opt, arg in opts:
        if opt in ('-h','--help'):
            usage()
            sys.exit()
        elif opt in ('-d','--directory'):
            directory=arg
        elif opt in ('-a','--author'):
            author = arg
        elif opt in ('-t','--type'):
            file_type = arg
        elif opt in ('-o','--time out'):
            time_out = float(arg)

    if len(args)>0:
        name = args[0]

    if len(args)>1:
        author =args[1]
    yahoo=yahoomp3(time_out,directory)

    if name == '':
        usage()
    elif author == '':
        author=get_author(name)
        yahoo.down_music(name,author,file_type)
    else:
        yahoo.down_music(name,author,file_type)

def usage():
    print 'usage: down_music [option] music_name \noptions:  \n -a --author  author name for search \n -t --type  music type for search \n -d --directory   set the download directory \n '
    pass

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

附件:ID3.py downmp3.py