zoukankan      html  css  js  c++  java
  • 解析邻居的耳朵音乐地址(单页下载)

        偶尔听歌的时候发现了一个很小众的音乐分享网站,邻居的耳朵,有个人的电台类型,属于音乐分享+文字分享,觉得很不错。从域名来看,属于多米旗下的网站:http://ear.duomi.com/  看来多米收购了很多这样的小站,包括之前的songtaste也被多米收下了。

       

        针对这样的网站尝试着自己去发掘音乐的真实链接,然后得到一个下载小工具,有了这么个初衷就开始尝试寻找真实链接的蛛丝马迹了。首先从crifan大神那里学习到可以利用IE提供的F12功能去分析一系列的请求过程,然后可以得到下面的一个记录:

        

        然而,这条记录是如何得到的呢,从抓取包的记录里面完全没有一些记录,不像crifan在分析songtaste的时候那么复杂,这里就是比较突兀的出现了请求这个url的http的get请求。然而可以看到这个请求是flash播放器发起的,所以一个不错的方法就是将上面的flash播放器下载然后进行反编译,查看一下flash播放器大概是如何发起请求的。

        这里有一个在线反编译swf的网站:http://www.showmycode.com/ ,我把swf的播放器下载然后提交得到类似如下的代码,其实不会AS的代码,不过扫到下面的时候感觉loadsound应该就是我想要的,百度下果然,src参数应该就是需要的音乐的地址了,但是src怎么传入进来的似乎没有从这个代码中感受的到,毕竟不会as,这里不深入研究了,从网页的源代码了解一下,看能否发现一些线索。

        

        打开网页的源代码查看,会发现这行非常像想要的信息,但是soundfile似乎加密了一样。这里的加密必定是可逆的,所以尝试了一下MD5和BASE64的解码,果然BASE64可以解析出地址:

        http://stream0.kxt.fm/dj/dangnikaishitingbuqizhegeshijiedeshengyin.mp3

        算是得到了想要的音乐地址结果了。

        

        

        接下来应该是从音乐地址进行下载了,但是这里存在一个问题,自己并未解决,因为自己尝试利用解析出的地址下载的时候出现拒绝访问,目前没找到好的解决方法,如果有遇到这种情况有解决方案的人提供下思路。

        

        上述分析完之后就尝试利用python简单的还原一下上面的过程,然而下载的部分还没找到解决方案。

        这个问题的来源其实就是因为没有完全模拟IE9中F12捕获的请求,参考评论中方法,服务器那边应该有check Referer这个头。但是由于之前用chrome插件postman怎么仿真header都无法成功,这里吐槽一下postman这个插件,这里找了其他的chrome的http request插件,竟然成功获取了音乐数据。

        看来这个问题解决了,这里就可以下载音乐了,方法即在http请求的时候参照设定一下header的信息,最重要的信息就是Referer信息了,表明你是flash播放器的身份~,服务器才无法知道你到底是不是播放器。

        代码实现的时候是利用urllib的urlretrieve方法获取文件,网上关于urllib如何设置header信息的方法特别少,大多都会让你选择利用urllib2代替,不过找了好久还是找到了替代的方法。参考python的一个mail list;

        https://mail.python.org/pipermail/python-list/2009-August/547234.html

        给出的解决方案的代码如下: 其中addheader是继承下来的Urlopener里的方法,这里直接拿来借用,urllib的原因就没有继续深究。

    import urllib
    
    class AppURLopener(urllib.FancyURLopener):
        version = "App/1.7"
        referrer = "http://ear.duomi.com/wp-content/plugins/audio-player/assets/player.swf?ver=2.0.4.1"
        def __init__(self, *args):
            urllib.FancyURLopener.__init__(self, *args)
            if self.referrer:
                self.addheader('Referer', self.referrer)
    
    urllib._urlopener = AppURLopener()

        

        代码主要基于urllib打开网页,然后利用re模块进行正则表达式的匹配出相应的模块,组合成想要的信息。其中base64解码的时候出现了问题,这里的方法是利用=号补齐。

        其中python的正则表达式参考:                 http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

        base64遇到“incorrect padding”问题参考: http://stackoverflow.com/questions/2941995/python-ignore-incorrect-padding-error-when-base64-decoding

        

    #coding=utf-8
    
    import urllib
    import re
    import base64
    import time
    import sys
    
    earurl = "http://ear.duomi.com/?p=296462"
    class AppURLopener(urllib.FancyURLopener):
        version = 'App/1.7'
        referer = 'http://ear.duomi.com/wp-content/plugins/audio-player/assets/player.swf?ver=2.0.4.1'
        def __init__(self, *args):
            urllib.FancyURLopener.__init__(self, *args)
            if self.referer:
                self.addheader('Referer',self.referer)
    
    class EarPageAnalysis:
        def __init__(self):
            self.title = ""
            self.singer = ""
            self.starttime = ""
            self.article = ""
            self.musicurl = ""
            self.musicname = ""
    
        def analysis(self,responsebody):
            #title,singer,starttime
            tss = r'<p><strong>(.*)<br />(.*)<br />(.*)<br />(.*)</strong></p>'
            tsspattern = re.compile(tss,re.S)
            tsslist = re.findall(tsspattern,responsebody)
            self.title = tsslist[0][0]
            self.singer = tsslist[0][1]
            self.starttime = tsslist[0][2]
    
            #article
            arti = r'</p>.*<p>(.*)</p>.*<p><span style="color: #808000;">'
            artipattern = re.compile(arti,re.S)
            artilist = re.findall(artipattern,responsebody)
            self.article = artilist[0]
    
            #musicurl
            music = r'AudioPlayer.embed(".*",.*{.*soundFile:"(.*)"});'
            musicpattern = re.compile(music,re.S)
            musiclist = re.findall(musicpattern,responsebody)
            missing_padding = 4 - len(musiclist[0]) % 4
            if missing_padding:
                musiclist[0] += b'=' * missing_padding
            self.musicurl = base64.b64decode(musiclist[0])
    
            tmplist = self.musicurl.split('/')
            self.musicname = tmplist[len(tmplist) - 1]
    
        def saveMusic(self):
            urllib._urlopener = AppURLopener()
            
            def reportHook(copiedBlocks, blockSize, totalFileSize):
                if copiedBlocks == 0:
                    print 'Begin to download, total size = %d' % (totalFileSize)
                else:
                    print 'Downloaded bytes: %d -- %d' % (copiedBlocks * blockSize,totalFileSize)
            
            urllib.urlretrieve(self.musicurl,self.musicname,reportHook)
    
        def showInfo(self):
            print self.title
            print self.singer
            print self.starttime
            print self.article
            print self.musicurl
    
    
    #test a best ear url
    page = urllib.urlopen(earurl)
    responsebody = page.read()
    pa = EarPageAnalysis()
    pa.analysis(responsebody)
    pa.showInfo()
    pa.saveMusic()
    

      

      简单的解析结果如下:

        

        音乐也下载成功了;

  • 相关阅读:
    Apache Thrift的简单使用
    ExternalInterface的简单使用方法
    Android各种屏幕分辨率(VGA、HVGA、QVGA、WQVGA、WVGA、FWVGA) 具体解释
    白话经典算法系列之六 高速排序 高速搞定
    HTML学习_01
    Codeforces Round #256 (Div. 2) A. Rewards
    activity
    自己生产签名和数字证书的方法
    Android项目目录结构
    Android程序的安装和打包
  • 原文地址:https://www.cnblogs.com/weixliu/p/4041530.html
Copyright © 2011-2022 走看看