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


    偶爾聽歌的時候發現了一個很小眾的音樂分享網站,鄰居的耳朵,有個人的電台類型,屬於音樂分享+文字分享,覺得很不錯。從域名來看,屬於多米旗下的網站: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()

  

  簡單的解析結果如下:

    

 

    音樂也下載成功了;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM