Chinaunix首页 | 论坛 | 博客
  • 博客访问: 263632
  • 博文数量: 42
  • 博客积分: 2245
  • 博客等级: 大尉
  • 技术积分: 466
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-20 13:02
文章分类

全部博文(42)

文章存档

2012年(4)

2011年(6)

2010年(2)

2009年(6)

2008年(24)

我的朋友

分类: Python/Ruby

2008-11-25 15:51:31

python程序,用wget下载baidu mp3,2008年11月20日下载成功,baidu会不定期改下载的地址,时间长了,这个程序可能会失效。


baidump3.py:
用法
Usage:
-h,     --help          This message
-s,     --song_name     Download single song
-t1,    --top=1         Download Baidu NewSong Top 100
-t2,    --top=2         Download Baidu Song Top 500


baidump3.py -t2 就可以下载Baidu歌曲排行500了。

\s+\s+"""
    reTop = re.compile(rePattern,re.S)
    return reTop.findall(html)


#-------- 破解baidu对url的变形处理,从加密的url还原出正确的mp3链接 --------------

def N(K,H,S,P,Q):
    #K存储ASCII字符 H存储字符在K中的位置,如Z(ASCII:90) H(90)=Z在K中的位置
    for R in range(S, P+1):
        K[R]=R+Q
        #print"K R=",R,K[R]
        H[R+Q]=R
    return(K,H)

def A(K,H,M,Q):
        #如Q="w884://0p2C9t6t2.CqEw.2t8/q03v/j403psUx0t7/HFFN-O/ONLJMKNH.14I"
        #print"Q=",Q
        #print"M=",M
        
        #for R in range(0,61):
        # print"K",R,K[R]
        P=len(Q)
        S=""
        for R in range(0, P):
                T=Q[R]
                #字符需要做变换
                if T >='A'and T <='Z'or T >='a'and T <='z'or T >='0'and T <='9':
                        
                        i = ord(T) #T的ASCII码
                        U = H[i]- M #在K中的映射-M偏移
                        if U < 0:
                                U+=62
                        
                        T = chr(K[U])
                        
                S+=T
        return S
def GetBaiduFLJ(content):
    """ 获取进行baidu mp3路径解密的F/L/J """

    k = content.find("var F=")
    if k ==-1:
            return 0
    k += len("var F=")
    str = content[k:-1]
    k = str.find(",")
    if k ==-1:
            return 0
    F = str[:k]
    k = str.find("var I=")
    if k ==-1:
            return 0
    k += len("var I=")+ 1
    str2 = str[k:-1]
    k = str2.find("\"")
    if k ==-1:
            return 0
    L = str2[:k]

    k = str2.find("J=")
    if k ==-1:
            return 0
    k += len("J=")+ 1
    str3 = str2[k:-1]
    k = str3.find("\"")
    if k ==-1:
            return 0
    J = str3[:k]
    #print"F=", F
    #print"L=", L
    #print"J=", J
    return[F,L,J]






def BaiduUncodingUrl(content):
    #baidu mp3 url 链接变形元素

    M = 0
    K=[]
    H=[]

    for i in range(0, 127):
            K.append(0)

    for j in range(0, 127):
            H.append(0)    

    [F,L,J]=GetBaiduFLJ(content)

    O=""
    E=""
    
    K,H=N(K,H,0,9,48) #K(0-9)='0'-'9'
    K,H=N(K,H,10,35,55) #K(10-35)='A'-'Z'
    K,H=N(K,H,36,61,61) #K(36-61)='a'-'z'
    #K:
    #0 1 2 3 4 5 6
    #012345678901234567890123456789012345678901234567890123456789012
    #01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
    
    M=string.atol(F)%26 #取余数,26个英文字符,M为偏移量
    ifnot M:
            M = 1
    
    O=A(K,H,M,L)
    if L == J:
            E = O
    else:
            E = A(K,H,M,J)
    #print"A(L)=O:",O
    #print"A(J):",A(J)
    return E


def DownloadTopListSong(TopList):
    #获取歌曲链接
    listSonglinks = GetTopLists(TopList)
    count=0
    for item in listSonglinks:
        # index song name
        print item[0]+"."+item[2] #+":"+item[1]
    #lm='-1'=任意 '0'=mp3 '1'=rm '2'=wma '3'=asf '4'=ram '5'=mid '6'=flash
        rePattern ="lm=-1&"
        reTop = re.compile(rePattern,re.S)
        urlMp3List=reTop.sub("lm=0&",item[1])
        song_name=string.zfill(item[0],3)+"."
        DownMp3(urlMp3List,song_name)
        count=count+1
        if count>=MAX_SONGS:
            break
            
def DownloadSingleSong(song_name):
    print song_name
    rePattern ="SONG_NAME"
    reTop = re.compile(rePattern,re.S)
    urlMp3List=reTop.sub(song_name,BaiduSongSearch)
    
    url2=UncodeUrl(urlMp3List)
    print url2
    DownMp3(url2,"")
    
def usage():
    print"Usage: "
    print"-h,    --help        This message"
    print"-s,    --song_name    Download single song"
    print"-t1,    --top=1        Download Baidu NewSong Top 100"
    print"-t2,    --top=2        Download Baidu Song Top 500"
    


def main():
    if len(sys.argv)< 2 :
        usage()
        sys.exit()
    try:
        opts, args = getopt.getopt(sys.argv[1:],"hs:t:",["help","song_name=","top="])
    except getopt.GetoptError,err:
        print"Error:",str(err),"\n"
        usage()
        sys.exit(2)
    for o,v in opts:
        if o in("-h","--help"):
            usage()
            sys.exit()
        elif o in("-s","--song_name"):
            song_name = v
            DownloadSingleSong(song_name)
        elif o in("-t","--top"):
            print"-t",v
            DownloadTopListSong(BaiduTopList[string.atoi(v)-1])
        else:
            print"Unknown parameter!"
            sys.exit()

if__name__=="__main__":
    main()

#!/usr/bin/python
# -*- coding:gbk -*-

import urllib
import htmllib
import formatter
import string
import os
import sys
import thread
import re
import subprocess
import getopt
#import threading

# 常量定义
# ###############################################################
BaiduTopList=[
# baidu新歌TOP100 链接
"",
# baidu歌曲TOP500 链接
""
]
# 百度歌曲搜索
BaiduSongSearch=""

#下载的歌曲的最大数目
MAX_SONGS=100
# 歌曲最小大小

SONG_MINSIZE=2
SONG_MAXSIZE=8
SONG_SIZEUNIT=1024*1024
# 文件覆盖
OVERWRITE=False

# 全局变量



def DownMp3(url,song_name_prefix):
    SongLink = GetSongLink(url)
    #print SongLink
    for item in SongLink:
        # index song_name songer mp3 size
        print "\t"+item[0]+"."+item[2]+"-"+item[4]+"."+item[6]+":"+item[5]+"M" #+item[1]
        if item[6] !="mp3":
            print "\tSkip",item[6]
            continue
        if string.atof(item[5]) <SONG_MINSIZE or string.atof(item[5]) >SONG_MAXSIZE:
            print "\tSkip",item[5],"M"
            continue
        song_name=song_name_prefix+item[2]+"_"+item[4]+".mp3"
        
        url2=UncodeUrl(item[1])
        content = DownObjectByUrl(url2)
        # baidu 解码 url
        mp3url = BaiduUncodingUrl(content)
        
        retCode=SaveFile(mp3url, ".",song_name)
        if retCode == 0 or retCode == 5:
            break;


def SaveFile(url, path,filename):
    """
    下载url指定的网络资源对象
    return result
    0 成功
    1 wget error, 2 User interrupt, 3 Execution failed, 4 size error, 5 file exist     
    "
""
    if not OVERWRITE:
        if os.path.exists(path+"\\"+filename):
            if os.path.getsize(path+"\\"+filename) > SONG_MINSIZE*SONG_SIZEUNIT :
                print filename+":exist"
                return 5
    
    url2 = UncodeUrl(url)
    print "\t"+path+"\\"+filename+" : "+url2
    cmd='wget -O'+filename+' -t5 -w2 -T10 '+url2
    #os.system(cmd)
    try:
        retcode = subprocess.call(cmd, shell = True)
        print "wget return code:",retcode
        if retcode!=0 :
            print "\tFailed"
            return 1
    except KeyboardInterrupt,e:
        print >>sys.stderr, "User Interrupt!",e
        return 2
    except OSError,e:
        print >>sys.stderr, "Execution failed!",e
        return 3
    
    if os.path.getsize(path+"\\"+filename) <SONG_MINSIZE*SONG_SIZEUNIT :
        print "\tFailed!"
        return 4
    print "\tOK"
    return 0



def UncodeUrl(url):
    """ url decode,主要是处理中文进行unicode编码的问题 """
    url2 = ""
    b = 0
    for c in url:
            i = ord(c)
            if b == 1:
                    b = 0
                    url2 += "%"
                    s = repr(hex(i))
                    url2 += s[-3] + s[-2]
                    continue
            if i >= 0x80:
                    url2 += "%"
                    s = repr(hex(i))
                    url2 += s[-3] + s[-2]
                    b = 1
            elif c == ' ':
                    url2 += "%20"
            else:
                    url2 += c
    return url2

def GetBaiduNextPageUrl(url):
        global pn
        url += "&rn=" + repr(rn) + "&pn=" + repr(pn) + "&ln=" + repr(ln)
        pn += 18
        return url

def DownObjectByUrl(url):
    try:
        fp = urllib.urlopen(url)
        content = ""
        sys.stdout.write("|")
        while 1:
            s = fp.read(8192)
            if not s:
                    break
            content += s
            sys.stdout.write("-")
            #print "=",
        fp.close()
        print "|"
        return content
            
    except :
        print "\tConnect error! "
        return ""
        
def GetTopLists(url):
    html = DownObjectByUrl(url)
    rePattern = """

%"[^>]+>([\d]+)\.%"[^>]+>([^"]+)" target=_blank>[<b>]*([^<]*)[</b>]*</a>"""
    reTop = re.compile(rePattern,re.S)
    return reTop.findall(html)
def GetSongLink(url):
    "
""
    0:index, 1:link, 2:song name 3:none 4:singer 5:size 6:type
    """
    html = DownObjectByUrl(url)
    rePattern = "
""<tr>\s+<td class=tdn>(\d+)</td>\s+<td class=d><a href="([^"]+)" title=[^#]+[^>]+>([^<]+)[^\n]+\s+
]+>(#c60a00">)?([^<]+)<[^\n]+\s+[^\n]+\s+[^\n]+\s+[^\n]+\s+[^\n]+\s+(\d+.\d+)\s+M([^<]+)

setup.py:
这个是打包程序,可以用py2exe将上述程序做成一个单独的exe文件,不再需要python的DLL库。

from distutils.core import setup
import py2exe

options = {"py2exe":
    {
        "compressed": 1,
        "optimize": 2,
        "bundle_files": 1
    }
}
#setup(console=['baidump3.py'])

setup(
    options = options,
    zipfile=None,
    console = [
        {
            "script": "baidump3.py", ### Main Python script
            "icon_resources": [(0, "..\images\MP3Get.ico")] ### Icon to embed into the PE file.
        }
    ],

阅读(7275) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-11-22 23:14:55

[url=http://www.1.net]室内装潢[/url]

chinaunix网友2009-11-22 23:14:02

室内装潢

chinaunix网友2009-02-19 20:18:07

牛b.. 我看过许多的都是多抓一个试听页面来获取地址的..