【提出问题】
autohome是个汽车门户,有时论坛里面会有一些比较好看的帖子,比如“一家四口环中国行”,主贴100多页,跟帖4000多页,看起来很爽。
但是,其论坛的JS脚本写的并不好,如果一帖图片非常多的情况下,经常有图片显示不了,很是郁闷。
于是有思路想下载帖子出来离线浏览。有人可能会说,现在有很多现成的离线浏览软件呀,不错,但是下载不了这里的图片,因为其图片URL做了个小小的手脚。
【分析问题】
1、URL规律分析
第一帖是
第二帖子
发现其N贴是
2、图片分析
查看源文件,其图片的HTML为
1 [/span>img id="img-0-8" name="lazypic" onload="tz.picLoaded(this)" onerror="tz.picNotFind(this)" style="width:700px;height:464px" src="" src9="" />
默认的src是一个等待图片,真实的src为src9属性,通过onload事件来替换src实现显示图片,超时或者出错是显示onerror事件
那么我们抓取src9就可以下载图片了
3、图片抓取尝试
比如上面的图片URL为 ,如果直接下载图片的话,服务器会拒绝,因为你在盗链。
所以最好是用HTTP 1.1的指令方式发起HTTP REQUEST,同时要传达 request.Referer 属性,可用fiddler监控
1 GET HTTP/1.1
2 Accept: /
3 Referer:
4 Accept-Language: zh-CN
5 User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; KB974487)
6 Accept-Encoding: gzip, deflate
7 Connection: Keep-Alive
8 DNT: 1
9 Host: club1.autoimg.cn
为了方便图片显示,建议按照原来的路径保存图片文件,比如图片 则按照文件夹 club1.autoimg.cn/album/userphotos/2013/4/3/500_43be_cde0b51b_cde0b51b.jpg 来保存。
4、分页链接
为了便于浏览,下载后的分页连接要能连上
1 [/span>div class="pages fs"
2 [/span>a href="forum-o-200042-1.html"
3 [/span>div class="pages" id="x-pages1" maxindex="4927"span class="cur"[/span>span class="fs" title="共 4927 页"
4 [/span>div class="jfwen"
5 到第[/span>spaninput type="text" value="" class="topinp txtcenter" id="txtGoFloor1" maxlength="7"
6 title="输入楼层数,按回车快速定位" onkeydown="if(event.keyCode==13){tz.goFloor(null,'txtGoFloor1')}" />
发现本来的连接就是html文件的文件名,所以只要按原来的文件名保存就可以了。
5、无用代码过滤
将onload和onerror事件去掉,将script的始末标签替换为DIV,将无用开头 替换为本地./,方便本地浏览不占资源
【解决问题】
1、http
1 private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
2 ///
3 /// 创建GET方式的HTTP请求 ,拿来的改了下
4 ///
5 ///
请求的URL
6 ///
请求的超时时间
7 ///
请求的客户端浏览器信息,可以为空
8 ///
请求来源URL
9 ///
随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空
10 ///
11 public static HttpWebResponse CreateGetHttpResponse(string url, int? timeout, string userAgent, string referer, CookieCollection cookies)
12 {
13 if (string.IsNullOrEmpty(url))
14 {
15 throw new ArgumentNullException("url");
16 }
17 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
18 request.Method = "GET";
19 request.UserAgent = DefaultUserAgent;
20 if (!string.IsNullOrEmpty(userAgent))
21 {
22 request.UserAgent = userAgent;
23 }
24 if (timeout.HasValue)
25 {
26 request.Timeout = timeout.Value;
27 }
28 if (referer != null)
29 {
30 request.Referer = referer;
31 }
32 if (cookies != null)
33 {
34 request.CookieContainer = new CookieContainer();
35 request.CookieContainer.Add(cookies);
36 }
37 return request.GetResponse() as HttpWebResponse;
38 }//代码效果参考:http://www.ezhiqi.com/bx/art_3933.html
2、主要动作按钮
1 private void btnStart_Click(object sender, EventArgs e)
2 {
3 btnStart.Enabled = false;
4 btnStop.Enabled = true;
5 timer1.Enabled = true;
6
7 var dt1 = DateTime.Now;
8 var dir = tbSaveDir.Text;
9 var baseUrl = tbURL.Text.Replace("-1.", "-#.");
10 var totalPage = (int) tbTotalPage.Value;
11 var fromPage = (int) tbFromPage.Value;
12 var isDefault = radioButton1.Checked;
13 var html = "";
14 var imgurl = "";
15 var htmlFile = "";
16 var imgNum = 0;
17
18 //进度条
19 progressBar1.Maximum = totalPage - fromPage + 1;
20 progressBar1.Value = 1;
21 progressBar2.Value = 1;
22
23 for (int i = fromPage; i <= totalPage; i++)
24 {
25 //处理进度条
26 progressBar1.Step = 1;
27 progressBar1.PerformStep();
28
29 //处理操作
30 var url = baseUrl.Replace("#", i.ToString());
31 try
32 {
33 var response = HttpWebResponseUtility.CreateGetHttpResponse(url, null, null, url, null);
34 if (response != null)
35 {
36
37 var sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("gb2312"),true);
38 html = sr.ReadToEnd();
39 response.Close();
40
41 string pattern = "src9=\""";
42 var gc = Regex.Matches(html, pattern);
43 //Console.WriteLine(gc);
44
45 //处理HTML文件
46 html = html.Replace("src=\"" src9=\"", "src=\"");
47 html = html.Replace("", "");
48 html = html.Replace("onload=", "x1=");
49 html = html.Replace("onerror=