MP3下载:baidu top100

MP3下载:baidu top100

注:本人初学python,把自己尝试编写的代码贴出来供大家一起学习。高人如有改进办法,欢迎指正!

[Copy to clipboard] [ - ]
CODE:
#!/usr/bin/python

import urllib
import urlparse
import htmllib
import formatter
import string
import os
import sys
import thread
#import threading

class Parser(htmllib.HTMLParser):
        #return a dictionary mapping anchor texts to lists of associated hyperlinks

        def __init__(self, verbose=0):
                self.anchors = {}
                f = formatter.NullFormatter()
                htmllib.HTMLParser.__init__(self, f, verbose)
        def anchor_bgn(self, href, name, type):
                self.save_bgn()
                self.anchor = href

        def anchor_end(self):
                text = string.strip(self.save_end())
                if self.anchor and text:
                        self.anchors[text] = self.anchors.get(text, []) + [self.anchor]

# 下载url指定的网络资源对象
def SaveFile(url, path):
        try:
                seps = url.split("/")
                size = len(seps)
                name = seps[size-1]
                #print url               
                name = path + "\\" + name

                url = UncodeUrl(url)
                if url.find(".mp3") == -1:
                        return 0;
                content = DownObjectByUrl(url)
                if len(content) < 1024*1024:
                        return 0;
                       
                if not os.path.exists(path):
                        os.mkdir(path)
               
                i = 1
                list = name.split(".")
                while os.path.exists(name):
                        if len(list) == 2:
                                name = list[0] + "_" + repr(i) + "." + list[1]
                        else:
                                name = list[0] + "_" + repr(i)
                        i += 1

                op = open(name, "wb")
                if not op:
                        print url + "\t[Failed]"
                        os.remove(name)
                        return 0               
                       
                op.write(content)
                op.close()
                print url + "\t[OK]"
                return 1
        except:
                print url + "\t[Failed]"
                try:
                        op.close()
                        os.remove(name)
                except:
                        return 0

                return 0

def DownObjectByUrl(url):
        fp = urllib.urlopen(url)
        content = ""
        while 1:
                s = fp.read(8192)
                if not s:
                        break
                content += s
        fp.close()
        return content

def GetNextRankLinks(url):       
        links = []
        html = DownObjectByUrl(url)
        p = Parser()
        p.feed(html)
        p.close()
        cnt = 0
        for k, v in p.anchors.items():
                for item in v:
                        links.append(item)

        return links


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

def N(S,P,Q):
        for R in range(S, P+1):
                K[R]=R+Q
                H[R+Q]=R       

def A(Q):
        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(Q[R])
                        U = H[i] - M
                        if U < 0:
                                U+=62
                        T =  chr(K[U])
                S+=T
        return S

def DisUrl():
        global K
        global H
        global M

        global F
        global L
        global J

        O=""
        E=""

        N(0,9,48)
        N(10,35,55)
        N(36,61,61)
       
        M=string.atoi(F)%26
        if not M:
                M = 1
       
        O=A(L)
        if L == J:
                E = O
        else:
                E = A(J)

        return E       

# 获取进行baidu mp3路径解密的F/L/J
def GetBaiduFLJ(content):
        global F
        global L
        global 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 l=") + 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]
       
        return 1
        #print "F=", F
        #print "L=", L
        #print "J=", J
       

#baidu mp3 url 链接变形元素
F = ""
L = ""
J = ""

M = 0
K=[]
H=[]

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

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


# url decode,主要是处理中文进行unicode编码的问题
def UncodeUrl(url):
        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


url1 = "http://list.mp3.baidu.com/list/newhits.html?top1"

def DownMp3(item):
        links2 = GetNextRankLinks(item)
        for item2 in links2:
                item2 =  UncodeUrl(item2)
                content = DownObjectByUrl(item2)
                if content == "":
                        continue
                if GetBaiduFLJ(content) == 0:
                        continue

                mp3url = DisUrl()
                if mp3url == "":
                        continue
                #mp3url = UncodeUrl(mp3url)
                #if mp3url.find(".mp3") == -1:
                #        continue
                if SaveFile(mp3url, "c:\\baidump3") == 1:
                        break
       
links = GetNextRankLinks(url1)
for item in links:
        if string.find(item, "http://") != -1 and string.find(item, "word=") != -1:
                print item
                thread.start_new_thread(DownMp3, (item,))

while True:
        pass

特别感谢:
yugliu

沙发
一直想做这样一个东东, 学习一下。
cool...
好 顶一个
呵呵,不错,把url加密的部分都解决了,我以前都是又利用搜索,解析出一个加密的url,然后再打开加密的url,取出真实地址出来
不好用呀!

if string.find(item, "http://") != -1 and string.find(item, "word=") != -1:   
2个判断应加括号吧

里面还有错的,是不是你自己编的程序?
小弟不才,自己写得。我自己测试过可以下载,不过速度不算快!如果有错误,敬请指出,谢谢!

QUOTE:
原帖由 yugliu 于 2008-9-17 15:48 发表
不好用呀!

if string.find(item, "http://") != -1 and string.find(item, "word=") != -1:   
2个判断应加括号吧

里面还有错的,是不是你自己编的程序?

这里的意思是必须同时找到"http://" 和"word="字符串,你说的加括号是指在那个地方加?是 (string.find(item, "http://") != -1) and (string.find(item, "word=") != -1) 这样?

你编的!!?? 很是让人怀疑,不知道你debug过没有
1.
thread.start_new_thread(DownMp3, (item,))
请检查 item 值, 里面有好多没用的项
2.
        if L == J:
                E = O
        else:
                E = A(J)

        return E        
你确定我们要的是 A(J)值,而不是O,有些L是不等于J的
3.
for i in range(0, 500):
        K.append(0)

for j in range(0, 500):
        H.append(0)
500??!!这个值太大了,怀疑你没理解baidu的解码程序

4.
SaveFile(url, path):

这个URL值你看过没有?有好多url值里有空格?什么原因??

以上4点问题,请解释!!
如果真是你写的程序,我要说你的编程态度有问题,这种非常明显的错误不应当出现的!
Python小弟初学,这个是为了学习urllib这个库而写的一个测试程序,里面确实有些错误,贴在这里并不是作为专业的东西发布,而是为了和大家一起学习,如果得到大家的指正那属于额外收获了。

下来我尽量回答您的疑问,有些无法回答的也给出原因。

QUOTE:
1.
thread.start_new_thread(DownMp3, (item,))
请检查 item 值, 里面有好多没用的项

首先说明,这里传进去的并不是mp3的链接,而是一个输入关键字然后搜索的网页的url。在百度进行搜索的时候,关键字在url中的位置是"word="字符串的后面,比如我们搜索s.h.e,点击提交之后,我们得到一个url:“http://mp3.baidu.com/m?tn=baidum ... li=2&word=s.h.e”。目前程序的做法是,如果某个url包含“http://”,并且包含“word=”,程序就认为这个url是一个包含搜索关键字的url。
当然,如果有更好的过滤的方法,大家都可以自己加,如果能够回帖提出来那更好了。

QUOTE:
2.
        if L == J:
                E = O
        else:
                E = A(J)

        return E        
你确定我们要的是 A(J)值,而不是O,有些L是不等于J的

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

for j in range(0, 500):
        H.append(0)
500??!!这个值太大了,怀疑你没理解baidu的解码程序

问题2和3都是关于baidu对mp3链接进行反向变形的代码,这些代码基本遵照baidu的原有代码,大家可以参考下面的代码(来源于baidu网页),个人认为baidu对这个简单的变形可能随时会更新。至于那个500太大的问题,我当时只是想得到一个已经初始化的列表,大小我也不确定,所以就写了个500。

QUOTE:
<script>
function G(A){return document.getElementById(A)}function sa(){var C=G("adv";if(C.innerHTML){var B=520,A=530;var E=(screen.width-B)/2,D=(screen.height-A)/2;moveTo(E,D);resizeTo(B,A)}}var song_1221789905;function sd(B){var A=new Image();A.src="/wd/sg-url.jpg?url="+song_1221789905+"&pos="+B+"&r="+Math.random()}function disUrl(){var F=1221789905,L=0;var I="s440://DCJ.G.D.FI/9u3/f0wzloQtwp/DBBHCDDCEEDCHDEDDE.x0E",J="s440://DCJ.G.D.FI/9u3/f0wzloQtwp/DBBHCDDCEEDCHDEDDE.x0E";var O="",E="";var K=[],H=[];var B=G("urln",C=G("urla";function N(S,P,Q){for(var R=S;R<=P;R++){K[R]=R+Q;H[R+Q]=R}}N(0,9,4;N(10,35,55);N(36,61,61);var M=F%26;M=M?M:1;function A(Q){var P=Q.length;var S="";for(var R=0;R<;R++){var T=Q.charAt(R);if(/[A-Za-z0-9]/.test(T)){var U=H[Q.charCodeAt(R)]-M;if(U<0){U+=62}T=String.fromCharCode(K[U])}S+=T}return S}O=A(I);E=(I==J)?O:A(J);B.href=C.href=song_1221789905=O;C.innerHTML=E;if(!L||F-L<3600){var D=new Image();D.src="/wd/mp3-sg-decode.jpg?url="+O+"&r="+Math.random()}}disUrl();
</script>



QUOTE:
4.
SaveFile(url, path):

这个URL值你看过没有?有好多url值里有空格?什么原因??

url显示的时候出现空格我注意过,url都是从网页里面直接获取出来,然后经过baidu反向变形,最后再进行unicode hex编码。在调试的时候,显示的空格其实是零值,主要从变形的url获取正常的url里面出现这个问题,如果需要修改这个问题,可能需要对baidu的变形进行更多研究(而且baidu top100和baidu普通的mp3搜索的变形也有些许差别)。
这是一个错误的还原:
变形后:5HHD://KKK.M6M6BKyB4.0CA/sDjCy1d692/QOOWXWSRXVWWVV.ADR
还原后:http://www.yiyinwang.com/UpLoadFice/2008*843*78877.mp3 (其中的*表示出现零值的情况)
下面是一个正确的还原:
变形后: 6IIE://RQX.RPU.RSX.QXW/LB/HDJG13S/VPPVSUPSSQPR_b_.BES
还原后: http://218.205.238.187/wm/source3/600635033102_C_.mp3
这个问题我一直解决不了,如果有人愿意分析的话可以从上面的baidu脚本里面去分析,留给强人分析了。