解析鄰居的耳朵音樂地址(單頁下載)

    偶爾聽歌的時候發現了一個很小衆的音樂分享網站,鄰居的耳朵,有我的的電臺類型,屬於音樂分享+文字分享,以爲很不錯。從域名來看,屬於多米旗下的網站:http://ear.duomi.com/  看來多米收購了不少這樣的小站,包括以前的songtaste也被多米收下了。html

   

    針對這樣的網站嘗試着本身去發掘音樂的真實連接,而後獲得一個下載小工具,有了這麼個初衷就開始嘗試尋找真實連接的蛛絲馬跡了。首先從crifan大神那裏學習到能夠利用IE提供的F12功能去分析一系列的請求過程,而後能夠獲得下面的一個記錄:python

    

    然而,這條記錄是如何獲得的呢,從抓取包的記錄裏面徹底沒有一些記錄,不像crifan在分析songtaste的時候那麼複雜,這裏就是比較突兀的出現了請求這個url的http的get請求。然而能夠看到這個請求是flash播放器發起的,因此一個不錯的方法就是將上面的flash播放器下載而後進行反編譯,查看一下flash播放器大概是如何發起請求的。正則表達式

    這裏有一個在線反編譯swf的網站:http://www.showmycode.com/ ,我把swf的播放器下載而後提交獲得相似以下的代碼,其實不會AS的代碼,不過掃到下面的時候感受loadsound應該就是我想要的,百度下果真,src參數應該就是須要的音樂的地址了,可是src怎麼傳入進來的彷佛沒有從這個代碼中感覺的到,畢竟不會as,這裏不深刻研究了,從網頁的源代碼瞭解一下,看可否發現一些線索。chrome

    

    打開網頁的源代碼查看,會發現這行很是像想要的信息,可是soundfile彷佛加密了同樣。這裏的加密一定是可逆的,因此嘗試了一下MD5和BASE64的解碼,果真BASE64能夠解析出地址:服務器

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

    算是獲得了想要的音樂地址結果了。工具

    

    

    接下來應該是從音樂地址進行下載了,可是這裏存在一個問題,本身並未解決,由於本身嘗試利用解析出的地址下載的時候出現拒絕訪問,目前沒找到好的解決方法,若是有遇到這種狀況有解決方案的人提供下思路。post

    

 

    上述分析完以後就嘗試利用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()

  

  簡單的解析結果以下:

    

 

    音樂也下載成功了;

相關文章
相關標籤/搜索