偶爾聽歌的時候發現了一個很小衆的音樂分享網站,鄰居的耳朵,有我的的電臺類型,屬於音樂分享+文字分享,以爲很不錯。從域名來看,屬於多米旗下的網站: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()
簡單的解析結果以下:
音樂也下載成功了;