最新消息:20190717 VPS服务器:Vultr新加坡,WordPress主题:大前端D8,统一介绍入口:关于

【教程】如何用IE9的F12去抓取某首Songtaste歌曲的真实地址

Crawl_EmulateLogin crifan 2723浏览 0评论

【背景】

先说的是,自己之前写了个小软件,用于下载songtaste中的歌曲:

最新版本是1.5:

downloadSonstasteMusic(下载Songtaste歌曲) v1.5 – 下载Songtaste(ST)中正在播放的歌曲/单首歌曲/整张专辑

 

最近发现,有个特殊的songtaste中的歌曲,无法下载。

对应地址为:

http://www.songtaste.com/song/2169436/

所以,就需要去搞懂为何无法下载。

就需要用到工具去分析背后的逻辑。

所以此处就去记录,或者说顺带演示一下,如何通过IE9的F12,去分析抓取,该首songtaste歌曲的真实url地址,以及这个地址是如何产生的。

 

提示:

1.不了解songtaste和想要下载songtaste中的歌曲的,自己去看:

【史上最全】如何下载songtaste网站上面的歌曲

2.关于网页抓取等相关逻辑不了解的,自己去看:

【整理】关于抓取网页,分析网页内容,模拟登陆网站的逻辑/流程和注意事项

【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程

【教程】如何利用IE9的F12去分析网站登陆过程中的复杂的(参数,cookie等)值(的来源)


下面记录整个过程:
1.打开IE9,打开F12,开始捕获,输入对应的上面的url地址,然后输入回车或点击Go:

start capturing input url go

2.然后就可以看到抓取的结果了:

captured log and see flash player

其中,上述ST的flash播放器,已经载入完毕,且已可以看到歌曲信息和播放时长。

说明,此时,真正的歌曲地址,已经获得了。

所以,接下来,就是,想要搞清楚,如何获得对应的歌曲的地址了。

3.此处,由于不知道具体的歌曲地址的值是什么,所以无法通过搜素某个关键字,而找到对应的歌曲地址。

但是此处由之前的知识所了解到了,对应的歌曲,十有八九是.mp3后缀。

所以,就先去找找.mp3,看看能否找到有价值的参考信息:

mp3 suffix to search

可以搜到一些相关的内容:

found first mp3 suffix

然后我们通过点击向右的箭头,一点点继续看下一个:

click next

然后看到跳转到对应的下一个了:

jump to next mp3

如此,一点点往下找,最后,我们可以找到一个,看起来像我我们所要的结果:

seem found real mp3 addr

4.然后,对于此处,看起来,像我我们所要找到歌曲的真正的地址:

http://m2.songtaste.com/201212071100/a83347112dd1ebb37f023e68db02aae7/2/24/2422838e2ba38cf633a36f74c5d4bdd8.mp3

我们好好去分析一下,此处对应的Response Body,即访问对应的url,所返回的结果,是如何获得的。

即对应的headers,cookie等相关信息,都是什么。

如果是POST,以及对应的post data都是什么。

 

提示:

不了解相关的header,cookie,post data的,可以去参考:

【整理】网页抓取,模拟登陆,抓取动态网页内容等过程中,所涉及的Headers信息,Cookie信息,POST数据的处理逻辑

 

要访问的url

url地址是:

http://www.songtaste.com/time.php

 

Request Headers

截图:

request headers

内容:

Key    Value
Request    POST /time.php HTTP/1.1
x-requested-with    XMLHttpRequest
Accept-Language    en-us
Referer    http://www.songtaste.com/song/2169436/
Accept    text/html, */*
Content-Type    application/x-www-form-urlencoded
Accept-Encoding    gzip, deflate
User-Agent    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)
Host    www.songtaste.com
Content-Length    116
Connection    Keep-Alive
Cache-Control    no-cache
Cookie    __utma=148846773.1834243366.1349920257.1354776054.1354847317.89; __utmz=148846773.1354847317.89.29.utmcsr=zhidao.baidu.com|utmccn=(referral)|utmcmd=referral|utmcct=/question/101394245.html; valid=1; pgv_pvi=6270354432; CookName=crifan; CookID=351979; CookPwd=6dd0c41612d2532ec3647e8e72fcb997; CookIcon=351979.gif; CookDmID=33897180; __utmb=148846773.22.10.1354847317; pgv_si=s5736732672; __utmc=148846773; valid=1; bdshare_firstime=1353551079520; PHPSESSID=925595afee7871fffb4f36c9070dde2c

 

Request Body,即Post data

截图:

request body that is post data

内容:

str=dcc505ff224130fe0ff0bb9bd7ffa907ef14c468ffae8e61b62d70f7043f13ced95bd52afec72ff62f1ced3fe51ffc51&sid=2169436&t=0

 

有了

url

headers(其中包含了cookie)

post data

就可以去实现对应的代码,去模拟此过程了。

但是很明显,在写代码模拟过程之前,还需要搞懂,其所headers,cookie,post data中的值,都是如何来的,如何得到的,才能写代码模拟出来。

 

此处,以此去分析一下相关的数据。

此处,最关心的数据,明显是Post data中的各个值,所以先去分析这些:

str=dcc505ff224130fe0ff0bb9bd7ffa907ef14c468ffae8e61b62d70f7043f13ced95bd52afec72ff62f1ced3fe51ffc51

去搜dcc505ff224130fe0ff0bb9bd7ffa907ef14c468ffae8e61b62d70f7043f13ced95bd52afec72ff62f1ced3fe51ffc51,最后可以找到出现的位置:

found str value

所以就是,我们可以通过访问:

http://www.songtaste.com/song/2169436/

然后从返回的html中,提取此处我们需要的这个值,即可。

这个很容易理解。

 

sid=2169436

这个更明显,2169436,就是songtaste歌曲的id,即本身所访问的url:

http://www.songtaste.com/song/2169436/

中的2169436。

所以也可以从url中提取出来。

 

t=0

t的值,很明显,固定都是设置为0.所以代码中,也可以设置为0即可。

 

所以,此处,加上之前所分析的songtaste中,关于获得对应的歌曲地址的方法,

再把此处的用于获取:

http://www.songtaste.com/song/2169436/

的歌曲真实地址的逻辑:

要访问的url方法(GET或POST)(如果是POST,所需的)post data必须的headers可能需要的cookie
http://www.songtaste.com/song/2169436/POST暂时可以试试,只是使用普通的header,看看能否正常获得返回值

目前觉得必须要有的是:
x-requested-with    XMLHttpRequest

暂时可以不发送cookie,看看是否可以正常获得所需数据

 

如此,就算是获得了对应的逻辑了。

如何从songtaste的歌曲的页面地址:

http://www.songtaste.com/song/2169436/

中,获得歌曲的,当时播放时刻的,真实地址:

http://m2.songtaste.com/201212071100/a83347112dd1ebb37f023e68db02aae7/2/24/2422838e2ba38cf633a36f74c5d4bdd8.mp3

提示:此地址过段时间就会失效,所以属于临时的,真实的地址,有时效性的。

所以,无法用于永久的外链的。

 

对应的代码实现,之前就已经实现了,摘录过来:

        // idOrUrl : 955407 or http://www.songtaste.com/song/955407 or http://www.songtaste.com/song/955407/
        // songInfo: the ST song info: title, artist, realAddr, ...
        // errStr: error reason string
        public bool getSongInfo(string idOrUrl, out songInfo songInfo, out string errStr)
        {
            bool getInfoOk = false;
            errStr = "未知错误!";
            songInfo = new songInfo();

            string songId = "";
            string songUrl = "";
            if (!isValidIdOrUrl(idOrUrl, out songId, out songUrl))
            {
                errStr = "无法识别的Songtaste的Id或Url:" + idOrUrl + " !";
                return getInfoOk;
            }
            else
            {
                songInfo.id = songId;
                songInfo.url = songUrl;
            }

            // here must clear previous cookies
            // otherwise access html with previous cookies will get fault html:
            //信息提示:   对不起,该用户不存在! 3 秒钟以后系统将自动跳转! 
            crl.clearCurCookies();

            string respHtml = "";
            respHtml = crl.getUrlRespHtml(songInfo.url, stHtmlCharset);
            if (respHtml != "")
            {
                //note: some song is illegal:
                //http://songtaste.com/song/3029002/
                //return invalid html content
                //following can not found valid info

                // 1. get song title and artist
                //<p class="mid_tit">╰.很多人都在找的一首伤感韩文丶最近很火﹀淑熙(啦啦啦)丶</p><p></p>
                string titleP = @"<p\s+?class=""mid_tit"">(?<title>.+?)</p>";
                Match foundTitle = (new Regex(titleP)).Match(respHtml);
                if (foundTitle.Success)
                {
                    songInfo.title = foundTitle.Groups["title"].Value;
                    songInfo.title = crl.removeInvChrInPath(songInfo.title);
                    songInfo.title = songInfo.title.Trim();

                    //<h1 class="h1singer">1956.烟蒂</h1>
                    //<h1 class="h1singer">Rie fu</h1>
                    //<h1 class="h1singer"></h1>
                    string singerP = @"<h1\s+?class=""h1singer"">(?<singer>.*?)</h1>";
                    Match foundSinger = (new Regex(singerP)).Match(respHtml);
                    if (foundSinger.Success)
                    {
                        songInfo.artist = foundSinger.Groups["singer"].Value;
                        //special: http://www.songtaste.com/song/809103/, no singer
                        if (songInfo.artist == "")
                        {
                            songInfo.artist = "Unknown Singer";
                        }
                        songInfo.artist = crl.removeInvChrInPath(songInfo.artist);
                        songInfo.artist = songInfo.artist.Trim();

                        // 2. get song real address
                        //<a href="javascript:playmedia1('playicon','player', '5bf271ccad05f95186be764f725e9aaf07e0c7791a89123a9addb2a239179e64c91834c698a9c5d82f1ced3fe51ffc51', '355', '68', 'b3a7a4e64bcd8aabe4cabe0e55b57af5', 'http://m3.', '3015123',0);ListenLog(3015123, 0);">
                        //http://www.songtaste.com/song/2428041/ contain:
                        //<a href="javascript:playmedia1('playicon','player', 'cachefile33.rayfile.com/12f1/zh-cn/download/d1e8d86a0a9880f697aee789f27383db/preview', '355', '68', 'b3a7a4e64bcd8aabe4cabe0e55b57af5', 'http://224.', '2428041',0);ListenLog(2428041, 0);">
                        //string songP = @"javascript:playmedia1\('playicon','player', '(?<str>\w+)', '\d+', '\d+', '\w+', '.+?', '(?<sid>\d+)',\d+\);";
                        string songP = @"javascript:playmedia1\('playicon','player', '(?<str>[^']+)', '\d+', '\d+', '(?<keyStr>\w+)', '(?<urlPref>.+?)', '(?<sid>\d+)',\d+\);";
                        Regex songRx = new Regex(songP);
                        Match foundSong = songRx.Match(respHtml);
                        if (foundSong.Success)
                        {
                            string str      = foundSong.Groups["str"].Value;
                            string urlPref  = foundSong.Groups["urlPref"].Value;
                            string keyStr   = foundSong.Groups["keyStr"].Value;
                            string sid      = foundSong.Groups["sid"].Value;

                            if (str.Contains("/"))
                            {
                                //cachefile33.rayfile.com/12f1/zh-cn/download/d1e8d86a0a9880f697aee789f27383db/preview
                                //to get the suffix
                                string suffix = "";
                                string mainJsUrl = "http://image.songtaste.com/inc/main.js";
                                string respHtmlMainJs = crl.getUrlRespHtml(mainJsUrl);
                                //		case "b3a7a4e64bcd8aabe4cabe0e55b57af5":
			                    //          return ".mp3";
                                string suffixP = @"""" + keyStr + @""":.+?return\s+""(?<suffix>\.\w+)"";";
                                Regex suffixRx = new Regex(suffixP, RegexOptions.Singleline);
                                Match foundSuffix = suffixRx.Match(respHtmlMainJs);
                                if (foundSuffix.Success)
                                {
                                    suffix = foundSuffix.Groups["suffix"].Value;
                                    songInfo.realAddr = urlPref + str + suffix;
                                }
                            }
                            else 
                            {
                                //5bf271ccad05f95186be764f725e9aaf07e0c7791a89123a9addb2a239179e64c91834c698a9c5d82f1ced3fe51ffc51

                                Dictionary<string, string> headerDict = new Dictionary<string, string>();
                                headerDict.Add("x-requested-with", "XMLHttpRequest");
                                // when click play
                                // access http://songtaste.com/time.php, post data:
                                //str=5bf271ccad05f95186be764f725e9aaf07e0c7791a89123a9addb2a239179e64c91834c698a9c5d82f1ced3fe51ffc51&sid=3015123&t=0
                                Dictionary<string, string> postDict = new Dictionary<string, string>();
                                postDict.Add("str", str);
                                postDict.Add("sid", sid);
                                postDict.Add("t", "0");
                                string getRealAddrUrl = "http://songtaste.com/time.php";
                                songInfo.realAddr = crl.getUrlRespHtml(getRealAddrUrl, headerDict, stHtmlCharset, postDict);    
                            }

                            if (songInfo.realAddr != "")
                            {
                                int lastPoint = songInfo.realAddr.LastIndexOf('.');
                                int strLen = songInfo.realAddr.Length;
                                songInfo.suffix = songInfo.realAddr.Substring(lastPoint);

                                songInfo.storedName = songInfo.title + " - " + songInfo.artist + songInfo.suffix;

                                getInfoOk = true;
                            }
                            else
                            {
                                errStr = "找不到歌曲的真实下载地址!";
                            }
                        }
                        else
                        {
                            errStr = "找不到歌曲的真实下载地址!";
                        }
                    }
                    else
                    {
                        errStr = "找不到歌曲的歌手信息!";
                    }
                }
                else
                {
                    errStr = "找不到歌曲的标题信息!";
                }
            }
            else
            {
                errStr = "无法获取网页信息!";
            }

            return getInfoOk;
        }

 

完整的代码,感兴趣的自行参考:

http://code.google.com/p/downloadsongtastemusic/source/browse/#svn%2Ftrunk

 

注:不了解google code的,自己去看:

【整理】google code简介和用法

 

另外,要说一下,本来开始说的是,此处的歌曲:

http://www.songtaste.com/song/2169436/

无法下载,以为是获得对应歌曲的播放地址的算法和之前不一样呢。

结果经过刚才的分析,得到的逻辑,和以前是一样的。

而无法下载歌曲的原因,是另外别处的代码的问题:

在申请了一个100M的buffer用于存放从songtaste的歌曲的数据,

结果由于此歌曲是160多MB,导致之前的100M的buffer不够用,而报错了。

这就是别的问题,需要我去想办法解决该问题。和此处的逻辑无关了。

 

【总结】

所以,简而言之,上述通过IE9去分析,如何从songtaste的url获得歌曲播放地址的逻辑,都是正确的。

而关于具体实现代码,去参考上面给出的google code上面的代码,即可。

转载请注明:在路上 » 【教程】如何用IE9的F12去抓取某首Songtaste歌曲的真实地址

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
59 queries in 0.232 seconds, using 19.03MB memory