抓取分析网页批量下载评书(3)之批量下载mp3


     本篇是大结局,看过前两篇的放心吧,不会有第四篇了,软件的下载地址,软件完成的效果你们本身看吧。

1、查找mp3文件的下载地址

     咱们首先要获取其下载地址,在评书的详细页中没有找到,咱们进入播放页面,看看能找到什么,以下图。


     直接定位到播放mp3的元素,此处用了一个iframe,说明本页面不是真正的播放页面,简单的看看,没发现什么有价值的内容,因而进入真正的播放页面寻求答案,可是出现了以下的提示:


    尝试换浏览器无果后,直接上大招,在评书详细页中按F12,选中网络标签,而后F5刷新页面,找到iframe中显示的网址记录, 使用 IE浏览器时,发现一个问题,URL连接中有许多乱码,因此此处建议用Chrome浏览器, 以下图



    在筛选框中输入mp3进行一下筛选,mp3这个关键字纯是猜想,不一样的状况要灵活调整,没想到第一次就蒙上了,两条结果正好是我想要的,第一条是真正的播放页面地址,第二条是mp3的下载地址。

    先选中播放页面那条记录,看右侧红框中的内容,在程序发起请求时把这项加上,这样就能得到页面的内容了,代码以下:

1
2
3
4
5
6
7
8
9

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(Url);
request.UserAgent =  "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
request.Accept =  "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";          
request.ContentType =  "application/x-www-form-urlencoded";
request.KeepAlive =  true;

//此处换上每集的网址
request.Referer =  "http://www.tingchina.com/pingshu/1228/play_1228_0.htm”; 
request.Method =  "GET";
        
      其实更简单的方法就是把请求标头里的内容都补充上,不用猜到底哪项起做用了。
      
      播放页的内容能抓取到了,接下来咱们分析一下mp3的下载地址,看第二条记录,就是mp3的地址,看下图。


      有了mp3的下载地址,咱们看看播放mp3页面的html代码,看看mp3下载地址是怎么生成的,咱们选中开发工具中的Elements标签,而后点击一下最左侧的放大镜,选中播放mp3的元素,接着 咱们按一下Ctrl+F,出现查询框,从mp3的下载地址中找部份内容填进去,例如我 填写的是 mp3?key= ,而后回车,就定位到咱们想要的内容,实际中,若是找不到能够尝试换搜索的关键词,仍是不行,就把只能逐行看代码,进行查找了,以下图。

    
      有了这些数据,我们简单分析一下就能看出, url[2]  加上 url[3]等于mp3的下载地址,接下来就简单了,开始下载吧。

2、具体的代码以下

 C# Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
 
/// <summary>
/// 抓取网页内容
/// </summary>
/// <param name="Url">网址</param>
/// <param name="myEncoding">编码方式</param>
/// <param name="myEncoding">请求的网址</param>
/// <returns></returns>
public   string  GetHtml( string  Url, Encoding myEncoding,  string  Referer)
{
    
string  HtmlString =  "" ;
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(Url);
    request.Timeout = 
15  *  1000 ;
    request.KeepAlive = 
true ;
    request.AllowWriteStreamBuffering = 
true ;
    request.Credentials = System.Net.CredentialCache.DefaultCredentials;
    request.MaximumResponseHeadersLength = -
1 ;
    request.Referer = Referer;
    request.UserAgent = 
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" ;
    request.Accept = 
"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" ;            
    request.ContentType = 
"application/x-www-form-urlencoded" ;
    request.Method = 
"GET" ;
    
try
    {
        
using  (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
        {
            Stream resStream = response.GetResponseStream();
            StreamReader sr = 
new  StreamReader(resStream, myEncoding);
            HtmlString = sr.ReadToEnd();
        }
    }
    
catch  { }
    
return  HtmlString;
}
 
/// <summary>
/// 下载评书的后台线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private   void  bw_Download_DoWork( object  sender, DoWorkEventArgs e)
{
    
//图书下载的本地路径
     string  LocalPath = e.Argument.ToString();

    
//查询出全部未下载的剧集
    var query = from m  in   this ._list
                where m.Status != 
1  orderby m.ID ascending
                select m;

    
//并行循环
    var loopResult = Parallel.ForEach(
        query, 
        
new  ParallelOptions { MaxDegreeOfParallelism =  1  },
        (sound,loopStatue) =>{

            
//抓取剧集的详细页内容
             string  Html = GetHtml(sound.Url, Encoding.GetEncoding( "GB2312" ),  "" );
            
if  (Html !=  "" )
            {
                
//分析播放音频网页的相关数据
                Match ms_Info = Regex.Match(Html, @ "src=""/play/"  +  this ._category + @ "/flash.asp\?id=[\d]*&inum=[\d]*&flei=(?<Category>[\s\S]*?)&bookname=(?<BookName>[\s\S]*?)&filename=(?<FileName>[\s\S]*?).mp3&nexturl" , RegexOptions.IgnoreCase | RegexOptions.Multiline);
                
if  (ms_Info.Success)
                {
                    
//获取评书的最终名称和演播者
                     string [] tmp = ms_Info.Groups[ "BookName" ].Value.Split( '_' );
                    
if  (tmp.Length ==  2 )
                    {
                        sound.Title = tmp[
0 ];
                        sound.Performer = tmp[
1 ];
                    }
                    
else
                    {
                        sound.Title = ms_Info.Groups[
"BookName" ].Value;
                        sound.Performer = ms_Info.Groups[
"Category" ].Value;
                    }

                    
//播放mp3的网页地址
                     string  PlayUrl =  "http://www.tingchina.com"  + ms_Info.Value.Replace(@ "src=""" "" ).Replace(@ "&nexturl" "" );

                    
//评书的实际播放页面实际是嵌在详细页中的一个frame框架中,因此须要继续抓取播放评书的页面。
                    Html = GetHtml(PlayUrl, Encoding.Default, sound.Url);
                    
if  (Html !=  "" )
                    {
                        
//抓取下载MP3的地址
                        MatchCollection ms = Regex.Matches(Html, @ "url\[[\d]{1}\]= ""http://t(?<Number>[\d]*).tingchina.com""" , RegexOptions.IgnoreCase | RegexOptions.Multiline);

                        
//抓取下载MP3所需的Key
                        Match ms_Down = Regex.Match(Html, @ "key=(?<key>[\d\w_]*)"";" , RegexOptions.IgnoreCase | RegexOptions.Multiline);

                        
if  (ms.Count >  0  && ms_Down.Success)
                        {
                            
//音频mp3下载地址
                             string  DownUrl =  string .Format( "http://t{0}.tingchina.com/{1}/{2}/{3}/{4}.mp3?key={5}" , ms[ 0 ].Groups[ "Number" ].Value,  this ._category, ms_Info.Groups[ "Category" ].Value, ms_Info.Groups[ "BookName" ].Value, ms_Info.Groups[ "FileName" ].Value, ms_Down.Groups[ "key" ].ToString());

                            WebClient client = 
new  WebClient();
                            client.Headers.Add(
"Accept" "*/*" );
                            client.Headers.Add(
"Accept-Encoding" "gzip, deflate" );
                            client.Headers.Add(
"Cache-Control" "no-cache" );
                            client.Headers.Add(
"Host" "t"  + ms[ 0 ].Groups[ "Number" ].Value +  ".tingchina.com" );
                            client.Headers.Add(
"Cookie" "Hm_lvt_99c9da471c839d239f4f41b80b233115=1445870536,1446212277,1446474813" );
                            client.Headers.Add(
"UserAgent" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" );
                            client.Headers.Add(
"Referer" "http://www.tingchina.com/play/newflashv4.swf" );
                            client.Headers.Add(
"x-flash-version" "20,0,0,267" );
                            
try
                            {
                                
//开始下载MP3
                                client.DownloadFile(DownUrl, LocalPath + (sound.ID +  1 ).ToString().PadLeft( 3 '0' ) + @ ".mp3" );
                                sound.Status = 
1 ;
                            }
                            
catch  (Exception ex)
                            {
                                sound.Status = -
1 ;
                                sound.Error = 
"下载MP3失败,缘由:"  + ex.Message;
                            }
                        }
                        
else
                        {
                            sound.Status = -
1 ;
                            sound.Error = 
"解析评书播放页的代码失败。" ;
                        }
                    }
                    
else
                    {
                        sound.Status = -
1 ;
                        sound.Error = 
"抓取播放页的Html代码失败。" ;
                    }
                }
                
else
                {
                    sound.Status = -
1 ;
                    sound.Error = 
"解析详细页的Html代码失败。" ;
                }
            }
            
else
            {
                sound.Status = -
1 ;
                sound.Error = 
"抓取详细页的Html代码失败。" ;
            }
        }
    );
}

private   void  bw_Download_RunWorkerCompleted( object  sender, RunWorkerCompletedEventArgs e)
{
    
if  (! this .IsDisposed)
    {
        var query = from m 
in   this ._list
                    where m.Status != 
1
                    orderby m.ID ascending
                    select m;

        
if  (query.Count() >  0 )
        {
            
this .btn_Download.Text =  "继续下载" ;
        }
        
else
        {
            
this .btn_Download.Text =  "下载完毕" ;
        }
    }

        
private   void  btn_Download_Click( object  sender, EventArgs e)
{
    
//本地保存的路径
     string  LocalPath = Path.Combine( this ._outpath,  this ._title) + @ "\" ;
    
if  (!Directory.Exists(LocalPath))
    {
        
try
        {
            Directory.CreateDirectory(LocalPath);
        }
        
catch  (Exception ex)
        {
            MessageBox.Show(
"建立评书下载目录失败,缘由:"  + ex.Message);
        }
    }

    
using  (BackgroundWorker bw_Download =  new  BackgroundWorker())
    {
        bw_Download.WorkerReportsProgress = 
true // 设置能够通告进度
        bw_Download.RunWorkerCompleted +=  new  RunWorkerCompletedEventHandler(bw_Download_RunWorkerCompleted);
        bw_Download.DoWork += 
new  DoWorkEventHandler(bw_Download_DoWork);
        bw_Download.RunWorkerAsync(LocalPath);
    }
}

    终于写完了,做为新手,可能写的比较啰嗦,可是本意是但愿读者能根据三篇教程,一步一步的完成这个软件。
    上面贴出的代码为了读者阅读起来简单,去除掉了一些非核心的代码,因此和下载的软件可能有些出入。
    文中若是有什么错误或者你们有什么更好的方式,欢迎交流。
 
做者: 相信的勇气
本文为博主原创文章,欢迎转载分享但请注明出处及连接,不然将其追究法律责!
勤奋的男人和爱笑的女人,运气通常都不会太差。
相关文章
相关标签/搜索