(转)玩玩小爬虫——入门

原文地址:http://www.cnblogs.com/huangxincheng/archive/2012/11/02/2751977.html

 

   前段时间做一个产品,盈利方式也就是卖数据给用户,用wpf包装一下,当然数据提供方是由公司定向爬虫采集的,虽然在实际工作

中没有接触这一块,不过私下可以玩一玩,研究研究。

既然要抓取网页的内容,肯定我们会有一个startUrl,通过这个startUrl就可以用广度优先的方式遍历整个站点,就如我们学习数据结

构中图的遍历一样。

既然有“请求网页”和“解析网页”两部分,在代码实现上,我们得需要有两个集合,分别是Todo和Visited集合,为了简单起见,我们

从单机版爬虫说起,说起爬虫,就必然逃避不了海量数据,既然是海量数据,那么性能问题不容忽视,在Todo和Visited集合的甄别

上,我们选择用Queue和HashSet,毕竟HashSet在定位查找方面只需常量的时间,下面我们用活动图来阐述一下。

在广度优先的时候,我们需要注意两个问题:

①:有的时候网页是相对地址,我们需要转化为绝对地址。

②:剔除外链。

看看其中我们一个部门的官网,广度遍历一下,看看有多少链接,当然是剔除外链的。

复制代码
  1 using System;   2 using System.Collections.Generic;   3 using System.Linq;   4 using System.Text;   5 using System.Net;   6 using System.IO;   7 using System.Text.RegularExpressions;   8    9 namespace ConsoleApplication1  10 {  11     public class Program  12     {  13         static void Main(string[] args)  14         {  15             var crawler = new Crawler("http://www.weishangye.com/");  16   17             crawler.DownLoad();  18   19             //show 一下我们爬到的链接  20             foreach (var item in Crawler.visited)  21             {  22                 Console.WriteLine(item);  23             }  24         }  25     }  26   27     public class Crawler  28     {  29         //基地址  30         public static Uri baseUri;  31         public static string baseHost = string.Empty;  32   33         /// <summary>  34         /// 工作队列  35         /// </summary>  36         public static Queue<string> todo = new Queue<string>();  37   38         //已访问的队列  39         public static HashSet<string> visited = new HashSet<string>();  40   41         public Crawler(string url)  42         {  43             baseUri = new Uri(url);  44   45             //基域  46             baseHost = baseUri.Host.Substring(baseUri.Host.IndexOf('.'));  47   48             //抓取首地址入队  49             todo.Enqueue(url);  50         }  51   52         public void DownLoad()  53         {  54             while (todo.Count > 0)  55             {  56                 var currentUrl = todo.Dequeue();  57   58                 //当前url标记为已访问过  59                 visited.Add(currentUrl);  60   61                 var request = WebRequest.Create(currentUrl) as HttpWebRequest;  62   63                 var response = request.GetResponse() as HttpWebResponse;  64   65                 var sr = new StreamReader(response.GetResponseStream());  66   67                 //提取url,将未访问的放入todo表中  68                 RefineUrl(sr.ReadToEnd());  69             }  70         }  71   72         /// <summary>  73         /// 提取Url  74         /// </summary>  75         /// <param name="html"></param>  76         public void RefineUrl(string html)  77         {  78             Regex reg = new Regex(@"(?is)<a[^>]*?href=(['""]?)(?<url>[^'""\s>]+)\1[^>]*>(?<text>(?:(?!</?a\b).)*)</a>");  79   80             MatchCollection mc = reg.Matches(html);  81   82             foreach (Match m in mc)  83             {  84                 var url = m.Groups["url"].Value;  85   86                 if (url == "#")  87                     continue;  88   89                 //相对路径转换为绝对路径  90                 Uri uri = new Uri(baseUri, url);  91   92                 //剔除外网链接(获取顶级域名)  93                 if (!uri.Host.EndsWith(baseHost))  94                     continue;  95   96                 if (!visited.Contains(uri.ToString()))  97                 {  98                     todo.Enqueue(uri.ToString());  99                 } 100             } 101         } 102     } 103 }
复制代码

当然还有很多优化的地方,既然是开篇也就这样了,快速入门才是第一位。 

posted on 2012-11-03 17:26  黑子范  阅读(223)  评论(0编辑  收藏  举报

导航