爬虫开发(一)
爬虫主要用来做数据采集,又名网络蜘蛛,内容网站很多就是用爬虫来抓取数据的。本系列(现在还不知道有几篇)旨在实现一个基本的爬虫程序(框架)。开发语言:C#
爬虫是要从源源不断的抓取到的页面中过滤出我需要的目标数据。既然要源源不断的抓取数据,那么我们就要有一个各个页面的URL的集合,去模拟访问这些URL,来分析返回的数据,从而再根据我们分析的HTML DOM结构获取到我们需要的数据。
URL的获取,通常,我们应该有一个Root节点,也就是根URL,然后就像树形结构一样去遍历他的各个子节点。说的形象一点,比如,一个网站的首页,上面有各个导航的URL1、URL2,URL3……也就是说只要我们获取到了网站首页的数据,然后筛选出所有的URL,就能获取这个根URL的直接子节点。然后我们再获取URL1的数据,从而获取URL1的直接子节点,然后一直这样重复下去,最后我们就可以得到一个庞大的树形结构。
数据的获取,每请求一个URL都会返回数据,也就是HTML文档的源码,我们要获取目标数据就要弄明白文档结构,而不同的页面有不同的文档结构。废话不多说了,程序员之间交流,还是直接上代码更容易理解。
对于Http访问,这里使用WebClient。新建一个Crawler的类库,并且新建一个Crawler类,代码如下:
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 8 namespace Crawler 9 { 10 /// <summary> 11 /// 爬虫 12 /// </summary> 13 public class Crawler 14 { 15 /// <summary> 16 /// 基URI 17 /// </summary> 18 public string BaseUri { get; set; } 19 20 /// <summary> 21 /// 构造函数 22 /// </summary> 23 /// <param name="url">基URI</param> 24 public Crawler(string baseUri) 25 { 26 this.BaseUri = baseUri; 27 } 28 29 /// <summary> 30 /// 构造函数 31 /// </summary> 32 public Crawler() { } 33 34 /// <summary> 35 /// 保存数据处理程序 36 /// </summary> 37 public Action<string> SaveHandler; 38 39 /// <summary> 40 /// 采集数据 41 /// </summary> 42 public void Crawl(string targetUri) 43 { 44 WebClient webClient = new WebClient(); 45 46 // 设置基URI 47 webClient.BaseAddress = this.BaseUri; 48 49 // 获取流 50 StreamReader reader = new StreamReader(webClient.OpenRead(targetUri), Encoding.UTF8); 51 52 // 读取数据 53 string html = reader.ReadToEnd(); 54 55 // 关闭流 56 reader.Close(); 57 58 // 保存结果 59 this.Save(html); 60 61 } 62 63 /// <summary> 64 /// 保存数据 65 /// </summary> 66 /// <param name="html">数据</param> 67 private void Save(string html) 68 { 69 SaveHandler(html); 70 } 71 } 72 }
这样一个很简单的爬虫类就写完了,我们可以试着调用一下,新建一个控制台应用程序,代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using Crawler; 6 7 namespace CrawlerConsole 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 14 Crawler.Crawler crawler = new Crawler.Crawler("http://www.baidu.com"); 15 16 crawler.SaveHandler = new Action<string>(html => Console.WriteLine(html)); 17 18 crawler.Crawl("/"); 19 20 } 21 } 22 }
然后我们Ctrl+F5运行一下,就可以看到我们爬到的百度首页的源码输出到控制台了。
简单介绍一下代码中几个需要注意的地方:
基URI:就是相对地址的主URI,我Crawl方法的参数就要要爬的地址,"/"相对于基URI"http://www.baidu.com"来说就是本页面,也就是首页。看MSDN的解释,BaseAddress 属性包含一个组合了相对地址的基 URI。调用上载或下载数据的方法时,WebClient 对象将此基 URI 与您在方法调用中指定的相对地址进行组合。如果指定的是绝对 URI,则 WebClient 不使用 BaseAddress 属性值。若要移除以前设置的值,请将 BaseAddress 设置为 null 引用(在 Visual Basic 中为 Nothing) 或空字符串 ("")。
WebClient.OpenRead():
OpenRead 方法创建一个 Stream 实例,该实例用于读取 address 参数指定的资源的内容。此方法在打开流时阻止。若要在等待流的同时继续执行,请使用 OpenReadAsync方法之一。
如果 BaseAddress 属性不是空字符串 (""),且 address 不包含绝对 URI,则 address 必须是相对 URI,此 URI 与 BaseAddress 组合在一起构成所请求数据的绝对 URI。如果QueryString 属性不为 null 引用(在 Visual Basic 中为 Nothing),则将它追加到 address。
关于WebClient的更多信息请参照MSDN:http://msdn.microsoft.com/zh-cn/library/tt0f69eh(v=vs.100).aspx
先这样吧,我会尽量抓紧写后面的篇章,最近实在是忙,月底要离职了,还连加六天班。。。