c#抓取网页数据(在页面抓取时应该注意到的几个问题(图) )
优采云 发布时间: 2022-02-08 00:21c#抓取网页数据(在页面抓取时应该注意到的几个问题(图)
)
在本文中,我们将讨论抓取页面时应注意的几个问题。
一:网页更新
我们知道一般网页中的信息是不断更新的,这也需要我们定期去抓取这些新的信息,但是我们应该如何理解这个“周期性”,也就是需要多长时间?
抓取一次页面,其实这段时间也是页面缓存时间。我们不需要在页面缓存时间内再次爬取页面,但是会给服务器带来压力。
比如我要爬博客园的首页,先清除页面缓存,
从 Last-Modified 到 Expires 可以看到博客园的缓存时间是 2 分钟,我也可以看到当前服务器时间 Date,如果我再
如果页面被刷新,这里的Date会变成下图中的If-Modified-Since,然后发送给服务器判断浏览器的缓存是否已经过期?
最后服务端找到If-Modified-Since >= Last-Modified的时间,服务端返回304,但是发现这个cookie信息真的是贼多。. .
在实际开发中,如果我们知道网站缓存策略,我们可以让爬虫每2分钟爬一次。当然,这些可以由数据团队配置和维护。
好吧,让我们用爬虫来模拟它。
1using System;
2using System.Net;
3
4namespace ConsoleApplication2
5{
6 public class Program
7 {
8 static void Main(string[] args)
9 {
10 DateTime prevDateTime = DateTime.MinValue;
11
12 for (int i = 0; i 0)
23 {
24 request.IfModifiedSince = prevDateTime;
25 }
26
27 request.Timeout = 3000;
28
29 var response = (HttpWebResponse)request.GetResponse();
30
31 var code = response.StatusCode;
32
33 //如果服务器返回状态是200,则认为网页已更新,记得当时的服务器时间
34 if (code == HttpStatusCode.OK)
35 {
36 prevDateTime = Convert.ToDateTime(response.Headers[HttpResponseHeader.Date]);
37 }
38
39 Console.WriteLine("当前服务器的状态码:{0}", code);
40 }
41 catch (WebException ex)
42 {
43 if (ex.Response != null)
44 {
45 var code = (ex.Response as HttpWebResponse).StatusCode;
46
47 Console.WriteLine("当前服务器的状态码:{0}", code);
48 }
49 }
50 }
51 }
52 }
53}
54
2:网络编码的问题
有时候我们已经抓取了网页,再去解析的时候,tmd全是乱码,真是操蛋,比如下面这样,
或许我们依稀记得html的meta中有一个叫charset的属性,里面记录了编码方式,另外一个关键点是
编码方式也记录在属性response.CharacterSet中,我们再试一次。
妈的,还是乱码,好痛。这个时候需要去官网看看http头信息中在交互什么。为什么浏览器可以正常显示?
如果爬行动物爬过来,它就行不通了。
查看http头信息,我们终于知道浏览器说我可以解析gzip、deflate、sdch这三种压缩方式。服务器发送gzip压缩,所以这里是
我们还应该了解常见的 Web 性能优化。
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6using HtmlAgilityPack;
7using System.Text.RegularExpressions;
8using System.Net;
9using System.IO;
10using System.IO.Compression;
11
12namespace ConsoleApplication2
13{
14 public class Program
15 {
16 static void Main(string[] args)
17 {
18 //var currentUrl = "http://www.mm5mm.com/";
19
20 var currentUrl = "http://www.sohu.com/";
21
22 var request = WebRequest.Create(currentUrl) as HttpWebRequest;
23
24 var response = request.GetResponse() as HttpWebResponse;
25
26 var encode = string.Empty;
27
28 if (response.CharacterSet == "ISO-8859-1")
29 encode = "gb2312";
30 else
31 encode = response.CharacterSet;
32
33 Stream stream;
34
35 if (response.ContentEncoding.ToLower() == "gzip")
36 {
37 stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress);
38 }
39 else
40 {
41 stream = response.GetResponseStream();
42 }
43
44 var sr = new StreamReader(stream, Encoding.GetEncoding(encode));
45
46 var html = sr.ReadToEnd();
47 }
48 }
49}
50
三:网页分析
现在网页经过一番努力已经得到了,接下来就是解析它了。当然,正则匹配是一个很好的方法。毕竟工作量还是比较大的,业界可能也会尊重。
HtmlAgilityPack,一个解析工具,可以将Html解析成XML,然后使用XPath提取指定的内容,极大的提高了开发速度,提升了性能。
还不错,毕竟敏捷也意味着敏捷。关于XPath的内容,这两张W3CSchool的图大家看懂就OK了。
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading;
6using HtmlAgilityPack;
7using System.Text.RegularExpressions;
8using System.Net;
9using System.IO;
10using System.IO.Compression;
11
12namespace ConsoleApplication2
13{
14 public class Program
15 {
16 static void Main(string[] args)
17 {
18 //var currentUrl = "http://www.mm5mm.com/";
19
20 var currentUrl = "http://www.sohu.com/";
21
22 var request = WebRequest.Create(currentUrl) as HttpWebRequest;
23
24 var response = request.GetResponse() as HttpWebResponse;
25
26 var encode = string.Empty;
27
28 if (response.CharacterSet == "ISO-8859-1")
29 encode = "gb2312";
30 else
31 encode = response.CharacterSet;
32
33 Stream stream;
34
35 if (response.ContentEncoding.ToLower() == "gzip")
36 {
37 stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress);
38 }
39 else
40 {
41 stream = response.GetResponseStream();
42 }
43
44 var sr = new StreamReader(stream, Encoding.GetEncoding(encode));
45
46 var html = sr.ReadToEnd();
47
48 sr.Close();
49
50 HtmlDocument document = new HtmlDocument();
51
52 document.LoadHtml(html);
53
54 //提取title
55 var title = document.DocumentNode.SelectSingleNode("//title").InnerText;
56
57 //提取keywords
58 var keywords = document.DocumentNode.SelectSingleNode("//meta[@name='Keywords']").Attributes["content"].Value;
59 }
60 }
61}
62
1 
2