當前位置:
首頁 > 知識 > 網路爬蟲——抓取時的幾個小細節

網路爬蟲——抓取時的幾個小細節

這一篇我們聊聊在頁面抓取時應該注意到的幾個問題。

一:網頁更新

我們知道,一般網頁中的信息是不斷翻新的,這也要求我們定期的去抓這些新信息,但是這個「定期」該怎麼理解,也就是多長時間需要

抓一次該頁面,其實這個定期也就是頁面緩存時間,在頁面的緩存時間內我們再次抓取該網頁是沒有必要的,反而給人家伺服器造成壓力。

就比如說我要抓取博客園首頁,首先清空頁面緩存,

從Last-Modified到Expires,我們可以看到,博客園的緩存時間是2分鐘,而且我還能看到當前的伺服器時間Date,如果我再次

刷新頁面的話,這裡的Date將會變成下圖中 If-Modified-Since,然後發送給伺服器,判斷瀏覽器的緩存有沒有過期?

最後伺服器發現If-Modified-Since = Last-Modifined的時間,伺服器也就返回304了,不過發現這cookie信息真是賊多啊。。。

在實際開發中,如果在知道網站緩存策略的情況下,我們可以讓爬蟲2min爬一次就好了,當然這些都是可以由數據團隊來配置維護了,

好了,下面我們用爬蟲模擬一下。

1 using System;

2 using System.Net;

3

4 namespace 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 10; i )

13 {

14 try

15 {

16 var url = http://cnblogs.com;

17

18 var request = (HttpWebRequest)HttpWebRequest.Create(url);

19

20 request.Method = Head;

21

22 if (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 }

二:網頁編碼的問題

有時候我們已經抓取到網頁了,準備去解析的時候,tmd的全部是亂碼,真是操蛋,比如下面這樣,

或許我們依稀的記得在html的meta中有一個叫做charset的屬性,裡面記錄的就是編碼方式,還有一個要點就是

response.CharacterSet這個屬性中同樣也記錄了編碼方式,下面我們再來試試看。

艹,居然還是亂碼,蛋疼了,這次需要到官網上面去看一看,到底http頭信息裡面都交互了些什麼,憑什麼瀏覽器能正常顯示,

爬蟲爬過來的就不行。

查看了http頭信息,終於我們知道了,瀏覽器說我可以解析gzip,deflate,sdch這三種壓縮方式,伺服器發送的是gzip壓縮,到這裡

我們也應該知道了常用的web性能優化。

1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading;

6 using HtmlAgilityPack;

7 using System.Text.RegularExpressions;

8 using System.Net;

9 using System.IO;

10 using System.IO.Compression;

11

12 namespace 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 }

三:網頁解析

既然經過千辛萬苦拿到了網頁,下一個就要解析了,當然正則匹配是個好方法,畢竟工作量還是比較大的,可能業界也比較推崇

HtmlAgilityPack這個解析工具,能夠將Html解析成XML,然後可以用XPath去提取指定的內容,大大提高了開發速度,性能也

不賴,畢竟Agility也就是敏捷的意思,關於XPath的內容,大家看懂W3CSchool的這兩張圖就OK了。

1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using System.Threading;

6 using HtmlAgilityPack;

7 using System.Text.RegularExpressions;

8 using System.Net;

9 using System.IO;

10 using System.IO.Compression;

11

12 namespace 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 }

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 千鋒JAVA開發學院 的精彩文章:

使用Elasticsearch搭建一個文件搜索系統
Kotlin技術分享-異常

TAG:千鋒JAVA開發學院 |