用C#实现网络爬虫.doc_第1页
用C#实现网络爬虫.doc_第2页
用C#实现网络爬虫.doc_第3页
用C#实现网络爬虫.doc_第4页
用C#实现网络爬虫.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

网络爬虫在信息检索与处理中有很大的作用,是收集网络信息的重要工具。接下来就介绍一下爬虫的简单实现。爬虫的工作流程如下爬虫自指定的URL地址开始下载网络资源,直到该地址和所有子地址的指定资源都下载完毕为止。下面开始逐步分析爬虫的实现。 1. 待下载集合与已下载集合为了保存需要下载的URL,同时防止重复下载,我们需要分别用了两个集合来存放将要下载的URL和已经下载的URL。因为在保存URL的同时需要保存与URL相关的一些其他信息,如深度,所以这里我采用了Dictionary来存放这些URL。具体类型是Dictionary 其中string是Url字符串,int是该Url相对于基URL的深度。每次开始时都检查未下载的集合,如果已经为空,说明已经下载完毕;如果还有URL,那么就取出第一个URL加入到已下载的集合中,并且下载这个URL的资源。 2. HTTP请求和响应C#已经有封装好的HTTP请求和响应的类HttpWebRequest和HttpWebResponse,所以实现起来方便不少。为了提高下载的效率,我们可以用多个请求并发的方式同时下载多个URL的资源,一种简单的做法是采用异步请求的方法。控制并发的数量可以用如下方法实现 1 private void DispatchWork() 2 3 if (_stop) /判断是否中止下载 4 5 return; 6 7 for (int i = 0; i _reqCount; i+) 8 9 if (!_reqsBusyi) /判断此编号的工作实例是否空闲10 11 RequestResource(i); /让此工作实例请求资源12 13 14 由于没有显式开新线程,所以用一个工作实例来表示一个逻辑工作线程1 private bool _reqsBusy = null; /每个元素代表一个工作实例是否正在工作2 private int _reqCount = 4; /工作实例的数量 每次一个工作实例完成工作,相应的_reqsBusy就设为false,并调用DispatchWork,那么DispatchWork就能给空闲的实例分配新任务了。 接下来是发送请求 1 private void RequestResource(int index) 2 3 int depth; 4 string url = ; 5 try 6 7 lock (_locker) 8 9 if (_urlsUnload.Count 0)22 23 MemoryStream ms = new MemoryStream(rs.Data, 0, read); /利用获得的数据创建内存流24 StreamReader reader = new StreamReader(ms, _encoding);25 string str = reader.ReadToEnd(); /读取所有字符26 rs.Html.Append(str); / 添加到之前的末尾27 var result = resStream.BeginRead(rs.Data, 0, rs.BufferSize, /再次异步请求读取数据28 new AsyncCallback(ReceivedData), rs);29 return;30 31 html = rs.Html.ToString();32 SaveContents(html, url); /保存到本地33 string links = GetLinks(html); /获取页面中的链接34 AddUrls(links, depth + 1); /过滤链接并添加到未下载集合中35 36 _reqsBusyindex = false; /重置工作状态37 DispatchWork(); /分配新任务38 39 catch (WebException we)40 41 MessageBox.Show(ReceivedData Web + we.Message + url + we.Status);42 43 第14行获得了读取的数据大小read,如果read0说明数据可能还没有读完,所以在27行继续请求读下一个数据包;如果read=0说明所有数据已经接收完毕,这时rs.Html中存放了完整的HTML数据,就可以进行下一步的处理了。第26行把这一次得到的字符串拼接在之前保存的字符串的后面,最后就能得到完整的HTML字符串。 然后说一下判断所有任务完成的处理 1 private void StartDownload() 2 3 _checkTimer = new Timer(new TimerCallback(CheckFinish), null, 0, 300); 4 DispatchWork(); 5 6 7 private void CheckFinish(object param) 8 9 if (_workingSignals.IsFinished() /检查是否所有工作实例都为Finished10 11 _checkTimer.Dispose(); /停止定时器12 _checkTimer = null;13 if (DownloadFinish != null & _ui != null) /判断是否注册了完成事件14 15 _ui.Dispatcher.Invoke(DownloadFinish, _index); /调用事件16 17 18 第3行创建了一个定时器,每过300ms调用一次CheckFinish来判断是否完成任务。第15行提供了一个完成任务时的事件,可以给客户程序注册。_index里存放了当前下载URL的个数。该事件的定义是1 public delegate void DownloadFinishHandler(int count);2 3 / 4 / 全部链接下载分析完毕后触发5 / 6 public event DownloadFinishHandler DownloadFinish = null;3. 保存页面文件这一部分可简单可复杂,如果只要简单地把HTML代码全部保存下来的话,直接存文件就行了。 1 private void SaveContents(string html, string url) 2 3 if (string.IsNullOrEmpty(html) /判断html字符串是否有效 4 5 return; 6 7 string path = string.Format(01.txt, _path, _index+); /生成文件名 8 9 try10 11 using (StreamWriter fs = new StreamWriter(path)12 13 fs.Write(html); /写文件14 15 16 catch (IOException ioe)17 18 MessageBox.Show(SaveContents IO + ioe.Message + path= + path);19 20 21 if (ContentsSaved != null)22 23 _ui.Dispatcher.Invoke(ContentsSaved, path, url); /调用保存文件事件24 25 第23行这里又出现了一个事件,是保存文件之后触发的,客户程序可以之前进行注册。1 public delegate void ContentsSavedHandler(string path, string url);2 3 / 4 / 文件被保存到本地后触发5 / 6 public event ContentsSavedHandler ContentsSaved = null; 4. 提取页面链接提取链接用正则表达式就能搞定了,不懂的可以上网搜。下面的字符串就能匹配到页面中的链接http:/(w-+.)+w-+(/w- ./?%&=*)?详细见代码 1 private string GetLinks(string html) 2 3 const string pattern = http:/(w-+.)+w-+(/w- ./?%&=*)?; 4 Regex r = new Regex(pattern, RegexOptions.IgnoreCase); /新建正则模式 5 MatchCollection m = r.Matches(html); /获得匹配结果 6 string links = new stringm.Count; 7 8 for (int i = 0; i = _maxDepth)27 28 return; /深度过大29 30 foreach (string url in urls)31 32 string cleanUrl = url.Trim(); /去掉前后空格33 cleanUrl = cleanUrl.TrimEnd(/); /统一去掉最后面的/34 if (UrlAvailable(cleanUrl)35 36 if (cleanUrl.Contains(_baseUrl)37 38 _urlsUnload.Add(cleanUrl, depth); /是内链,直接加入未下载集合39 40 else41 42 / 外链处理43 44 45 46 第34行的_baseUrl是爬取的基地址,如/,将会保存为,当一个URL包含此字符串时,说明是该基地址下的链接;否则为外链。_baseUrl的处理如下,_rootUrl是第一个要下载的URL 1 / 2 / 下载根Url 3 / 4 public string RootUrl 5 6 get 7 8 return _rootUrl; 9 10 set11 12 if (!value.Contains(http:/)13 14 _rootUrl

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论