《简易网络爬虫程序的开发》由会员分享,可在线阅读,更多相关《简易网络爬虫程序的开发(21页珍藏版)》请在金锄头文库上搜索。
1、简易网络爬虫程序的开发简易网络爬虫程序的开发(c#(c#版版) )收藏收藏给大家共享下自己写的一个简易网络爬虫程序,本程序分为两部分:spider 程 序集与 spiderserver windows 服务程序,其中 spider 程序对爬虫程序的线程管 理与获取网页的 html 做了封装。先看看这个程序的类图吧:下面我对这些类一一介绍:HttpServer 类该类中只有一个方法 public string GetResponse(string url)功能是对指定 的 url 获取该页面的 html,实现该功能必须解决以下几个问题:1.如何获取指定 url 的 html?其实实现该功能很简单
2、,在 C#中通过 HttpWebResponse 类的调用就能实现,具 体方法是:HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);HttpWebResponse response = (HttpWebResponse)request.GetResponse();Stream reader = response.GetResponseStream();然后从 reader 流中读取内容就行了2.编码问题,网页通常使用 utf-8 或 gb2312 进行编码,如果程序在读取流时使 用了错误的编码会导致中文字符的错误为解
3、决这个问题我先看一小段某网页的 html百度一下,你就知道 在标签中会指定该页面的编码:charset=gb2312,所以我的程序中要先读 取 charset 的值,然后再重新按 charset 的值对读流进行读取,为了使这个过 程更加简单,我先统一按“gb2312“进行编码,从流中读取 html,在分析 html 的 charset 值,如果该值也是“gb2312“就直接返回 html,如果是其它编码就重 新读取流。3.对于有些页面的 html 可能会非常大所以我们要限制大小,在程序中最在读取 不会超过 100k该类完整代码如下:/ / HTTP 服务类/ internal class Ht
4、tpServer/ / 获取指定页面 html 文本/ / 页面 urlpublic string GetResponse(string url)trystring html = string.Empty;string encoding = string.Empty;HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);request.Method = “get“;request.ContentType = “text/html“;byte buffer = new byte1024;using (HttpWebResp
5、onse response = (HttpWebResponse)request.GetResponse()using (Stream reader = response.GetResponseStream()using (MemoryStream memory = new MemoryStream()int index = 1;int sum = 0;/限制的读取的大小不超过 100kwhile (index 0 sum += index;html = Encoding.GetEncoding(“gb2312“).GetString(memory.ToArray();if (string.I
6、sNullOrEmpty(html)return html;else/解析 charset 的值Regex re = new Regex(“charset=(?sS*?)“);Match m = re.Match(html.ToLower();encoding = m.Groups“charset“.ToString();if (string.IsNullOrEmpty(encoding) | string.Equals(encoding.ToLower(), “gb2312“)return html;else/不是 gb2312 编码则按 charset 值的编码 进行读取return En
7、coding.GetEncoding(encoding).GetString(memory.ToArray(); catchreturn “; 由于在程序外该类是不可见的,所以声明时用了 internal.AbsChain 类对于 AbsChain 采用的是职责链设计模式,目的是抽象出网络爬虫处理 html 的过 程,因为在 spider 程序集中并不真正处理如何解析 html,用户只需重载 AbsChain 类中的 process 方法,完成自定义的处理过程程序源码如下:namespace WebSpider / / 职责链抽象类/ public abstract class AbsChai
8、nprivate AbsChain _handler=null;private string _url = string.Empty;public string Url get return _url; set _url = value; internal AbsChain Handlergetreturn _handler;/ / 文本处理过程/ / html 文本protected abstract void Process(string html);/ / 设置下一个处理节点/ / 下一个处理节点public void SetProcessHandler(AbsChain handler
9、)_handler = handler;/ / 开始处理/ / html 文本流public void Start(string html)Process(html); /处理用户重载方法if (Handler != null)Handler.Url = Url;Handler.Start(html); ChainMain 类:ChainMain 类是对 AbsChain 类的具体实现,但是它的 Process 方法是个空方法, 所以你可以把它理解成它就是具体处理职责链上的头 节点,通过 ChainMain 类 的_handler 将处理任务往下传递,用户通过调用 ChainMain 的 Se
10、tProcessHandler 方法设置下 一个处理节点,这个节点必须由用户继承 AbsChain 并实现抽象方法 Process。ChainMain 类的源代码如下:namespace WebSpider internal class ChainMain : AbsChainprotected override void Process(string html) WorkThread 类:WorkThread 类是工作线程类,每个工作线程类都包括一个职责链的头节点 ChainMain、一个 HttpServer 类和一个 UrlStack,其中 UrlStack 类采用了单 构件设计模式,所
11、以对于整个应该用程序都是使用一个 UrlStack 对象。源代码如下:namespace WebSpider / / 工作线程/ internal class WorkThreadprivate ChainMain _chainHeader = new ChainMain();private HttpServer _httpServer = new HttpServer();private bool _isRun = false;/ / 职责链的头节点/ public ChainMain ChainMaingetreturn _chainHeader;public HttpServer Htt
12、pServergetreturn _httpServer;public bool IsRun get return _isRun; public UrlStack UrlStackgetreturn UrlStack.Instance; / / 工作线程入口函数/ / 种子 urlpublic void Start()try_isRun = true;while (_isRun)/从地址堆栈中取出 urlstring url = UrlStack.Pop();if (!string.IsNullOrEmpty(url)string html = _httpServer.GetResponse(
13、url);if (!string.IsNullOrEmpty(html)ChainMain.Url = url;ChainMain.Start(html);catch/ / 停止工作线程/ public void Stop()_isRun = false; Start 方法是工作线程的入口方法,它从 UrlStack 中取出 url,并调用 HttpServer 的 GetResponse 方法取出 Url 对应 网页的 HTML 代码,并将 HTML 代码传递给职责链的头节点 ChainMain,由它的 Start 方法开始处理。回忆一 下 AbsChain 的 Start()方法,它是先调
14、用自身类的 Process 方法,然后再调用 _handler.Start()方法,就这样把处理过程传递下去。UrlStack 类:UrlStack 类非常的简单,它采用单构件设计模式,并维护了一个数据结构,该 数据结构用来存储需要爬虫抓取的 Url源码如下:namespace WebSpider public class UrlStackprivate static UrlStack _urlstack = new UrlStack();private Queue _stack = new Queue();private readonly int _maxLength = Convert.T
15、oInt32(System.Configuration.ConfigurationManager.AppSettings “MaxLength“);private UrlStack() public static UrlStack Instanceget return _urlstack; public void Push(string url)lock (this)if (!_stack.Contains(url)if (_stack.Count = _maxLength)_stack.Dequeue();_stack.Enqueue(url);public string Pop()lock (this)if (_stack.Count 0)return _stack.Dequeue();elsereturn “;public int Count get return _stack.Count; 在源码中我用的是一个队列,当然,用户也可以改成其它的数据结构,比如: Stack,用队列就有点像广度优先搜索,用堆栈就有点像深度优先搜索。AbsThreadManager 类:AbsThreadManager 的主要功能是管理开启 WorkThread 工作线程,与监控线线 程的,W