使用C#实现蜘蛛程序知识整理_第1页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

1、使用c#实现蜘蛛程序知识整理"蜘蛛"(spider)是internet上一种很实用的程序,搜寻引擎利用蜘蛛程序将web页面收集到数据库,企业利用蜘蛛程序监视竞争对手的网站并跟踪变动,个人用户用蜘蛛程序下载web页面以便脱机用法,开发者利用蜘蛛程序扫描自己的web检查无效的链接对于不同的用户,蜘蛛程序有不同的用途。那么,蜘蛛程序到底是怎样工作的呢?蜘蛛是一种半自动的程序,就象现实当中的蜘蛛在它的web(蜘蛛网)上旅行一样,蜘蛛程序也根据类似的方式在web链接织成的网上旅行。蜘蛛程序之所以是半自动的,是由于它总是需要一个初始链接(动身点),但此后的运行状况就要由

2、它自己打算了,蜘蛛程序会扫描起始页面包含的链接,然后拜访这些链接指向的页面,再分析和追踪那些页面包含的链接。从理论上看,终于蜘蛛程序会拜访到internet上的每一个页面,由于internet上几乎每一个页面总是被其他或多或少的页面引用。本文介绍如何用c语言构造一个蜘蛛程序,它能够把囫囵网站的内容下载到某个指定的名目,程序的运行界面一。你可以便利地利用本文提供的几个核心类构造出自己的蜘蛛程序。图1c特殊适合于构造蜘蛛程序,这是由于它已经内置了http拜访和多线程的能力,而这两种能力对于蜘蛛程序来说都是十分关键的。下面是构造一个蜘蛛程序要解决的关键问题: html分析:需要某种html解析器来分

3、析蜘蛛程序碰到的每一个页面。 页面处理:需要处理每一个下载得到的页面。下载得到的内容可能要保存到磁盘,或者进一步分析处理。 多线程:惟独拥有多线程能力,蜘蛛程序才干真正做到高效。 确定何时完成:不要小看这个问题,确定任务是否已经完成并不容易,尤其是在多线程环境下。一、html解析c语言本身不包含解析html的能力,但支持xml解析;不过,xml有着严格的语法,为xml设计的解析器对html来说根本没用,由于html的语法要宽裕得多。为此,我们需要自己设计一个html解析器。本文提供的解析器是高度自立的,你可以便利地将它用于其它用c处理html的场合。本文提供的html解析器由parsehtml

4、类实现,用法十分便利:首先创建该类的一个实例,然后将它的source属性设置为要解析的html文档:parsehtml parse = new parsehtml();parse.source = "hello world"接下来就可以利用循环来检查html文档包含的全部文本和标志。通常,检查过程可以从一个测试eof办法的while循环开头:while(!parse.eof()char ch = parse.parse()parse办法将返回html文档包含的字符-它返回的内容只包含那些非html标志的字符,假如碰到了html标志,parse办法将返回0值,

5、表示现在碰到了一个html标志。碰到一个标志之后,我们可以用gettag()办法来处理它。if(ch=0)htmltag tag = parse.gettag();?普通地,蜘蛛程序最重要的任务之一就是找出各个href属性,这可以借助c的索引功能完成。例如,下面的代码将提取出href属性的值(假如存在的话)。attribute href = tag"href"string link = href.value;?获得attribute对象之后,通过attribute.value可以得到该属性的值。二、处理html页面下面来看看如何处理html页面。首先要做的固

6、然是下载html页面,这可以通过c提供的httpwebrequest类实现:httpwebrequest request = (httpwebrequest)webrequest.create(m_uri);response = request.getresponse();stream = response.getresponsestream();?接下来我们就从request创建一个stream流。在执行其他处理之前,我们要先确定该文件是二进制文件还是文本文件,不同的文件类型处理方式也不同。下面的代码确定该文件是否为二进制文件。if( !response.contenttype.tolowe

7、r().startswith("text/") )savebinaryfile(response);return null;string buffer = "",line;?假如该文件不是文本文件,我们将它作为二进制文件读入。假如是文本文件,首先从stream创建一个streamreader,然后将文本文件的内容一行一行加入缓冲区。reader = new streamreader(stream);while( (line = reader.readline()!=null )buffer+=line+"

8、rn"?装入囫囵文件之后,接着就要把它保存为文本文件。savetextfile(buffer);?下面来看看这两类不同文件的存储方式。二进制文件的内容类型声明不以"text/"开始,蜘蛛程序挺直把二进制文件保存到磁盘,不必举行额外的处理,这是由于二进制文件不包含html,因此也不会再有需要蜘蛛程序处理的html链接。下面是写入二进制文件的步骤。首先预备一个缓冲区暂时地保存二进制文件的内容。 byte buffer = new byte1024;?接下来要确定文件保存到本地的路径和名称。假如要把一个网站的内容下载到本地的c:test文件夹,二

9、进制文件的网上路径和名称是则本地路径和名称应该是c:testimageslogo.gif。与此同时,我们还要确保c:test名目下已经创建了images子名目。这部分任务由convertfilename办法完成。string filename = convertfilename( response.responseuri );?convertfilename办法分别http地址,创建相应的名目结构。确定了输出文件的名字和路径之后就可以打开读取web页面的输入流、写入本地文件的输出流。stream outstream = file.create( filename );stream instre

10、am = response.getresponsestream();?接下来就可以读取web文件的内容并写入到本地文件,这可以通过一个循环便利地完成。int l;dol = instream.read(buffer,0,buffer.length);if(l>0)outstream.write(buffer,0,l); while(l>0);?写入囫囵文件之后,关闭输入流、输出流。outstream.close();instream.close();?比较而言,下载文本文件更简单一些。文本文件的内容类型总是以"text/"开始。假设文件已被下载并

11、保存到了一个字符串,这个字符串可以用来分析网页包含的链接,固然也可以保存为磁盘上的文件。下面代码的任务就是保存文本文件。string filename = convertfilename( m_uri );streamwriter outstream = new streamwriter( filename );outstream.write(buffer);outstream.close();?在这里,我们首先打开一个文件输出流,然后将缓冲区的内容写入流,最后关闭文件。三、多线程多线程使得计算机看起来就象能够同时执行一个以上的操作,不过,除非计算机包含多个处理器,否则,所谓的同时执行多个操作

12、仅仅是一种模拟出来的效果-靠计算机在多个线程之间迅速切换达到"同时"执行多个操作的效果。普通而言,惟独在两种状况下多线程才干实际上提高程序运行的速度。第一种状况是计算机拥有多个处理器,其次种状况是程序常常要等待某个外部大事。对于蜘蛛程序来说,其次种状况正是它的典型特征之一,它每发出一个url哀求,总是要等待文件下载完毕,然后再哀求下一个url。假如蜘蛛程序能够同时哀求多个url,明显能够有效地削减总下载时光。为此,我们用documentworker类封装全部下载一个url的操作。每当一个documentworker的实例被创建,它就进入循环,等待下一个要处理

13、的url。下面是documentworker的主循环:while(!m_spider.quit )m_uri = m_spider.obtainwork();m_spider.spiderdone.workerbegin();string page = getpage();if(page!=null)processpage(page);m_spider.spiderdone.workerend();?这个循环将向来运行,直至quit标志被设置成了true(当用户点击"cancel"按钮时,quit标志就被设置成true)。在循环之内,我们调用obtainwo

14、rk猎取一个url。obtainwork将向来等待,直到有一个url可用-这要由其他线程解析文档并寻觅链接才干获得。done类利用workerbegin和workerend办法来确定何时囫囵下载操作已经完成。从图一可以看出,蜘蛛程序允许用户自己确定要用法的线程数量。在实践中,线程的最佳数量受许多因素影响。假如你的机器性能较高,或者有两个处理器,可以设置较多的线程数量;反之,假如网络带宽、机器性能有限,设置太多的线程数量其实不一定能够提高性能。四、任务完成了吗?利用多个线程同时下载文件有效地提高了性能,但也带来了线程管理方面的问题。其中最复杂的一个问题是:蜘蛛程序何时才算完成了工作?在这里我们要

15、借助一个专用的类done来推断。首先有须要解释一下"完成工作"的详细含义。惟独当系统中不存在等待下载的url,而且全部工作线程都已经结束其处理工作时,蜘蛛程序的工作才算完成。也就是说,完成工作意味着已经没有等待下载和正在下载的url。done类提供了一个waitdone办法,它的功能是向来等待,直到done对象检测到蜘蛛程序已完成工作。下面是waitdone办法的代码。public void waitdone()monitor.enter(this);while ( m_activethreads>0 )monitor.wait(this);monit

16、or.exit(this);?waitdone办法将向来等待,直到不再有活动的线程。但必需注重的是,下载开头的最初阶段也没有任何活动的线程,所以很简单造成蜘蛛程序一开头就立刻停止的现象。为解决这个问题,我们还需要另一个办法waitbegin来等待蜘蛛程序进入"官方的"工作阶段。普通的调用次序是:先调用waitbegin,再接着调用waitdone,waitdone将等待蜘蛛程序完成工作。下面是waitbegin的代码:public void waitbegin()monitor.enter(this);while ( !m_started )monitor.

17、wait(this);monitor.exit(this);?waitbegin办法将向来等待,直到m_started标志被设置。m_started标志是由workerbegin办法设置的。工作线程在开头处理各个url之时,会调用workerbegin;处理结束时调用workerend。workerbegin和workerend这两个办法协助done对象确定当前的工作状态。下面是workerbegin办法的代码:public void workerbegin()monitor.enter(this);m_activethreads+;m_started = true;monitor.pulse(this);monitor.exit(this);?workerbegin办法首先增强当前活动线程的数量,接着设置m_started标志,最后调用pulse办法以通知(可能存在的)等

温馨提示

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

评论

0/150

提交评论