爬虫小记--抓取过程简要分析

     前段时间做一个产品。盈利方式也就是卖数据给用户,用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 @ 2017-08-08 19:00  brucemengbm  阅读(204)  评论(0编辑  收藏  举报