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

一、查找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的下载地址,接下来就简单了,开始下载吧。

二、具体的代码如下

 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 = ;
    request.KeepAlive = true;
    request.AllowWriteStreamBuffering = true;
    request.Credentials = System.Net.CredentialCache.DefaultCredentials;
    request.MaximumResponseHeadersLength = -;
    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 !=  orderby m.ID ascending
                select m;

//并行循环
    var loopResult = Parallel.ForEach(
        query, 
         },
        (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('_');
                    )
                    {
                        sound.Title = tmp[];
                        sound.Performer = tmp[];
                    }
                    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);

&& ms_Down.Success)
                        {
                            //音频mp3下载地址
].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(].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
, '0') + @".mp3");
                                sound.Status = ;
                            }
                            catch (Exception ex)
                            {
                                sound.Status = -;
                                sound.Error = "下载MP3失败,原因:" + ex.Message;
                            }
                        }
                        else
                        {
                            sound.Status = -;
                            sound.Error = "解析评书播放页的代码失败。";
                        }
                    }
                    else
                    {
                        sound.Status = -;
                        sound.Error = "抓取播放页的Html代码失败。";
                    }
                }
                else
                {
                    sound.Status = -;
                    sound.Error = "解析详细页的Html代码失败。";
                }
            }
            else
            {
                sound.Status = -;
                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 != 
                    orderby m.ID ascending
                    select m;

)
        {
            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);
    }
}

    终于写完了,作为新手,可能写的比较啰嗦,但是本意是希望读者能根据三篇教程,一步一步的完成这个软件。
    上面贴出的代码为了读者阅读起来简单,去除掉了一些非核心的代码,所以和下载的软件可能有些出入。
    文中如果有什么错误或者大家有什么更好的方式,欢迎交流。
 
本文为博主原创文章,欢迎转载分享但请注明出处及链接,否则将其追究法律责!
勤奋的男人和爱笑的女人,运气一般都不会太差。

抓取分析网页批量下载评书(3)之批量下载mp3的更多相关文章

  1. 【转】详解抓取网站,模拟登陆,抓取动态网页的原理和实现(Python,C#等)

    转自:http://www.crifan.com/files/doc/docbook/web_scrape_emulate_login/release/html/web_scrape_emulate_ ...

  2. selenium抓取动态网页数据

    1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...

  3. scrapy和selenium结合抓取动态网页

    1.安装python (我用的是2.7版本的) 2.安装scrapy:   详情请参考 http://blog.csdn.net/wukaibo1986/article/details/8167590 ...

  4. 数据抓取分析(python + mongodb)

    分享点干货!!! Python数据抓取分析 编程模块:requests,lxml,pymongo,time,BeautifulSoup 首先获取所有产品的分类网址: def step(): try: ...

  5. python数据抓取分析(python + mongodb)

    分享点干货!!! Python数据抓取分析 编程模块:requests,lxml,pymongo,time,BeautifulSoup 首先获取所有产品的分类网址: def step(): try: ...

  6. 利用wget 抓取 网站网页 包括css背景图片

    利用wget 抓取 网站网页 包括css背景图片 wget是一款非常优秀的http/ftp下载工具,它功能强大,而且几乎所有的unix系统上都有.不过用它来dump比较现代的网站会有一个问题:不支持c ...

  7. 使用scrapy-selenium, chrome-headless抓取动态网页

        在使用scrapy抓取网页时, 如果遇到使用js动态渲染的页面, 将无法提取到在浏览器中看到的内容. 针对这个问题scrapy官方给出的方案是scrapy-selenium, 这是一个把sel ...

  8. 抓取https网页时,报错sun.security.validator.ValidatorException: PKIX path building failed 解决办法

    抓取https网页时,报错sun.security.validator.ValidatorException: PKIX path building failed 解决办法 原因是https证书问题, ...

  9. python网络爬虫抓取动态网页并将数据存入数据库MySQL

    简述以下的代码是使用python实现的网络爬虫,抓取动态网页 http://hb.qq.com/baoliao/ .此网页中的最新.精华下面的内容是由JavaScript动态生成的.审查网页元素与网页 ...

随机推荐

  1. ssh设置无密码登录

    设置无密码登录此处设为有主机a登录到主机b 1.在主机a生成公钥 ssh-keygen -t rsa  之后有导航(其实一直回车就可以) 2.此时在主机a/home/YOURHOSTNAME/.ssh ...

  2. Java课堂测试01及感想

    上周进行了Java的开学第一次测验,按要求做一个模拟ATM机功能的程序,实现存取款.转账汇款.修改密码.查询余额的操作.这次测验和假期的试题最大的不同还是把数组存储改成的文件存储,在听到老师说要用文件 ...

  3. liunx基础命令

    linux的简单介绍 linux是一款免费使用和自由传播的内似于unix的操作系统软件,是一个基于POSI和unix的多用户,多任务,支持多线程和多CPU的一种操作系统.主要用于服务器,特别是网络服务 ...

  4. TortoiseGit使用笔记

    不喜欢敲命令行,或者用惯TortoiseSVN的也可以使用TortoiseGit 1. TortoiseGit安装 安装很简单,默认安装就可以.需要安装以下几个软件: l Git-2.14.3-64- ...

  5. ibatis注意要点

    一.ibatis的关键字like查询 select * from t_student where s_name '%张%'; 这种like语句在ibatis中怎么写,他们现在的项目是用ibatis作为 ...

  6. 2014年的最后一个程序,却成为了2015年的第一个bug

    这个点不睡觉的程序员,要么就是在努力学技术,要么就是代码出bug了.而我,是后者.呵呵,2015了,觉还是要睡的

  7. DDR4 PSOD输出的优点--DBI的优点

    DDR4是JEDEC组织关于DRAM器件的下一代标准.DDR4主要是针对需要高带宽低功耗的场合.这些需求导致了DDR4芯片引入了一些新的特点,这些新的特点,导致在系统设计中,引入一些新的设计需求. D ...

  8. 安装BouncyCastle

    对于Windows而言 将bcprov-jdk16-146.jar 复制到C:\Program Files\Java\jre6\lib\ext和C:\jdk1.6.0\jre\lib\ext目录下: ...

  9. 2.3.5使用原子类进行i++操作

    除了在i++操作时使用synchronized关键字实现同步外,还可以使用AtomicInteger原子类进行实现 原子操作时不可分割的整体,没有其他线程能够中断或检查正在原子操作的变量,一个原子类型 ...

  10. (转)FIKKER和Nginx的反向代理服务功能对比评测报告

    转自:http://tieba.baidu.com/p/1268737304 针对高并发反向代理服务器 NGINX和FIKKER评测报告 测试硬件环境:服务端:CPU:E5200硬盘:SATA 133 ...