继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

玩玩小爬虫——入门

慕用4979188
关注TA
已关注
手记 266
粉丝 63
获赞 531

     前段时间做一个产品,盈利方式也就是卖数据给用户,用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 }

复制代码

 

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

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP