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

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

  一:網頁更新web

  咱們知道,通常網頁中的信息是不斷翻新的,這也要求咱們按期的去抓這些新信息,可是這個「按期」該怎麼理解,也就是多長時間須要瀏覽器

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

  就好比說我要抓取博客園首頁,首先清空頁面緩存,性能優化

  


  從Last-Modified到Expires,咱們能夠看到,博客園的緩存時間是2分鐘,並且我還能看到當前的服務器時間Date,若是我再次服務器

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

  


  最後服務器發現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 }



  

相關文章
相關標籤/搜索