偶尔听歌的时候发现了一个很小众的音乐分享网站,邻居的耳朵,有我的的电台类型,属于音乐分享+文字分享,以为很不错。从域名来看,属于多米旗下的网站: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()
简单的解析结果以下:
音乐也下载成功了;