谁知道php网络爬虫代码码 提高搜索引擎的

抢先式多线程网络爬虫spider在智能搜索引擎中的实现 - 知识改变思维,思维改变生活 - ITeye技术网站
博客分类:
转自:《计算机工程》 文/ 董瑞洪,张秋余,唐静兵,张涛
&&&&&&& 线程是描述进程内的执行,正是线程负责执行包含在进程的地址空间中的代码。单个进程可能包含几个线程,它们可以同时执行进程的地址空间中的代码。每个线程有自己的一组cpu寄存器和堆。线程可以看成“一段代码的执行”也就是一系列有jvm执行的二进制指令。这里面没有对象甚至没有方法的概念。线程是有序的指令,而不是方法。
&&&&&&& 线程的数据结构,仅仅只包括执行这些指令的信息。它包含当前的运行上下文,如寄存器的内容,当前指令的在运行引擎的指令流中的位置,保存方法本地参数和变量的运行时堆栈。切换线程更有效率,时间单位是us。对于java而言,一个线程可以看作是jvm的一个状态。
&& 创建线程
&&&&&&&& java使用两种方法来处理多线程。
&&&&&&&&& 1.子类化Thread对象。Thread对象是java提供的封装线程的对象。要创建一个线程,必须创建一个从Thread对象类导出的新类。必须覆盖 Thread的run()函数来完成有用的工作。如果使用的类需要子类化另一个类,就不能子类化Thread对象。
&&&&&&&&& 2.实现Runnable接口。Runnable接口只有一个方法run(),我们声明自己的类实现Runnable接口并提供这一方法,将线程代码写入其中,就完成了这一部分的任务。但是Runnable接口并没有任何对线程的支持,还必须创建Thread类的实例,这一点通过Thread类的构造函数 public Thread(Runnable target)来实现。
&&&& 线程间通信
&&&&& 当线程在继续执行当前需要等待一个条件时,仅有synchronized关键字是不够的。虽然synchronized关键字阻止并非更新一个对象,但它并没实现线程间通信。Object类为此提供了3个函数:wait(),notify()和notifyAll()。以全球气候预测程序为例。这些程序通过将地球分为许多单元,在每个循环中,每个单元的计算都是隔离进行的,知道这些值趋于稳定,然后相邻单元之间就会交换一些数据。所以,从本质上讲,在每个循环中各个线程都必须等待所有线程完成各自的任务以后才能进入下一个循环。模型称为屏蔽同步。
&&&& spider程序的结构
&&&&& 构造spider程序有两种方式:1.把能spider程序设计为递归的程序 2.编写一个非递归的程序,它要维护一个要访问的网页列表。考虑使用哪一种方式的前提是,构造的spider程序必须能访问非常大的web站点。
&&&&& 本系统中使用了非递归的程序设计方法。这是因为,当一个递归程序运行时要把每次递归压入堆栈,但在本系统设计中使用的是多线程,它允许一次运行多个任务,但是,多线程与递归是不兼容的。因为在这一过程中每个线程都有自己的堆栈,而当一个方法调用它自身时,他们需要使用同一个堆栈。这意味着递归的 spider程序不可能使用多线程。
&&&&&& 数据库设计
&&&&& 在程序执行的过程中,考虑对储存网页的储存过程进行监控,以便决定spider程序对访问队列处理。因为,在数据库设计过程中,添加了网页储存状态这个字段。
&&&&&& 在Internet中,有很大一部分网页数据大于8000byte,如果用普通的二进制型字段(binary,varbinary)是不能完成存储要求的。因而,设计数据库中储存网页数据的字段为BLOB字段,实际使用为text类型。这就要求对该字段的储存和读取过程中,不能按照常规的字段读取方式进行。
&&&&&& 一个URL对应一个网页,选取网页数据对应的URL对位数据库中记录的主键,进行唯一标识。
&&&&&&& 类的设计
&&&&&& Getsite类,spider类,spiderInternalWolkload类,spiderWorker类,spiderDone 类,spiderSqlWorkload类,接口 spiderReportable, IWorkloadStorable
&&&&&& GetSite类为程序的入口,负责整个spider程序的运行。
&&&&&& 当创建一个spider程序时,需要使用spider类。spider类服务于3个目的:
&&&&&&&&&&&&&&&& 1.担当spider接口,为使用spider提供方法;
&&&&&&&&&&&&&&&& 2.这个对象管理线程池,并将spider的发现向启动此spider的对象报告(即spider对象和spiderWorker对象间通信)
&&&&&&&&&&&&&&&&& 3.检测spider何时完成是spider的任务。spider类必须坚持spider何时完成。这一任务有spiderdone类来完成。
&&&&&&&& SpiderWorker对象的目的是处理URL。
&&&&&&& 由于有很多并发的线程,要确切地知道spider何时完成是相当困难的。这需要一个对象来精确地跟踪有多少个线程仍在运行,spiderDone类就是为完成这一任务来设计的。
抢先式多线程spider程序的实现
&&&&&&& 由于spider是多线程的,必须有一种方法在不同的线程间分配任务。这个工作死有spiderWorker对象来完成的。通过这个对象维护线程池,可以承担spider创建和销毁线程对象的任务。
&&&&&&&& 我们的网络爬虫广泛使用了多线程,必须把任务分成很多小任务。spider的任务是下载一个web站点,并将网页内的链接加入到作业中来。 spiderWorker实现了这一个基本任务。当spider开始时,它创建一个处理spider发现网页的spiderWorker类池。
&&&&&&& 用spider的start()函数,该函数再调用run()。SpiderWorker对象的生成在spider类中,如以下代码所示:
public Spider(ISpiderReportable manager,String URL,HTTP http,int poolSize,IWorkerloadStorable w) {
_manager =
_workSpider =
_pool = new SpiderWorker[poolSize];
for( int i = 0; i& _pool.i++){
HTTP hc = http.copy();
_pool[i] = new SpiderWorker( this,hc);
&&& 其中,最后一行代码生成SpiderWorker对象。也就是说,在构造Spider对象的同时,生成了SpiderWorker对象进行线程的管理,并且生成了线程池。SpiderWorker对象的start()方法被调用后,开始执行SpiderWorker的run()方法,为进一步处理网页做好了准备。
&&&&&& 在已经初始化线程,发现待处理URL队列的基础上,SpiderWorker对象调用SpiderDone类的workerBegin()方法,唤醒已经初始化过的spider线程。
synchronize public void workBegin() {
_activeThreads ++;
_started =
&&&&&&& 线程的唤醒调用notify()方法。
&&&&&& 紧接着调用SpiderWorker对象的processWorkload()方法,进入到网页处理的真正执行代码,转入到类GetSite中。 processWorkload方法执行完毕,也就是说,该线程完成了自己的历史使命,执行了网页处理的过程,就应该为其他的线程让出资源,因为就应关闭该线程。执行SpiderDone类的 workerEnd()方法,如以下代码所示:
synchronized public void workerEnd() {
_activeThreads -- ;
浏览: 101418 次
来自: 成都
这样并不能完全解决黑莓的签名问题吧,一个项目里除了调用Disp ...
学习了,但是我有一个问题,error-code是在web.xm ...
大虾,能不能放源码啊........
呵呵,我个人觉得url去重应该不能算是一个有什么难度的问题或者 ...网络爬虫调研报告 - 张 作强 BLOG - ITeye技术网站
博客分类:
网络爬虫调研报告
项目中要对指定的网络资源进行抓取、存储、分类、索引、并提供检索服务。充当全文检索数据库的是组织下的开源项目检索工具,而只是个搜索引擎工具,它提供接口,通过编写程序对信息进行索引和检索,在其后台需要网络爬虫程序的支持,其目的是通过网络爬虫软件抓取网页,作为提供给搜索引擎的资源,进行索引和查询。
是基金会的一个开源项目,它原本是开源文件索引框架项目的一个子项目,后来渐渐发展成长为一个独立的开源项目。它基于开发,基于框架,提供网页爬虫和搜索引擎两部分功能。
主要分为两个部分:网页爬虫()和搜索引擎()。主要用于从网络上抓取网页并为这些网页建立索引。主要利用这些索引检索用户的查找关键词来产生查找结果。另外很吸引人的一点在于,它提供了一种插件框架,使得其对各种网页内容的解析、各种数据的采集、查询、集群、过滤等功能能够方便的进行扩展,正是由于有此框架,使得的插件开发非常容易,第三方的插件也层出不穷,极大的增强了的功能和声誉。
爬虫工作策略
爬虫的工作策略一般则可以分为累积式抓取()和增量式抓取()两种。
累积式抓取是指从某一个时间点开始,通过遍历的方式抓取系统所能允许存储和处理的所有网页。在理想的软硬件环境下,经过足够的运行时间,累积式抓取的策略可以保证抓取到相当规模的网页集合。但由于数据的动态特性,集合中网页的被抓取时间点是不同的,页面被更新的情况也不同,因此累积式抓取到的网页集合事实上并无法与真实环境中的网络数据保持一致。
增量式抓取是指在具有一定量规模的网络页面集合的基础上,采用更新数据的方式选取已有集合中的过时网页进行抓取,以保证所抓取到的数据与真实网络数据足够接近。进行增量式抓取的前提是,系统已经抓取了足够数量的网络页面,并具有这些页面被抓取的时间信息。
面向实际应用环境的网络蜘蛛设计中,通常既包括累积式抓取,也包括增量式抓取的策略。累积式抓取一般用于数据集合的整体建立或大规模更新阶段;而增量式抓取则主要针对数据集合的日常维护与即时更新。
在确定了抓取策略之后,如何从充分利用网络带宽,合理确定网页数据更新的时间点就成了网络蜘蛛运行策略中的核心问题。
总体而言,在合理利用软硬件资源进行针对网络数据的即时抓取方面,已经形成了相对比较成熟的技术和实用性解决方案,这方面目前所需解决的主要问题,是如何更好的处理动态网络数据问题(如数量越来越庞大的数据等),以及更好的根据网页质量修正抓取策略的问题。
工作流程图
工作流程:
建立初始集合分析
初始集的建立有两种方式:超链接和站长提交。
超链接是指机器人程序根据网页链到其他网页中的超链接,就像日常生活中所说的一传十,十传百一样,从少数几个网页开始,连到数据库上所有到其他网页的链接。理论上,若网页上有适当的超连结,机器人便可以遍历绝大部分网页。
站长提交是指在实际运行中,爬虫不可能抓取到所有站点,为此,网站站长可以向搜索引擎进行提交,要求收录,搜索引擎经过核查之后,便将该网站加入到集合中,进行抓取。
inject操作分析
操作调用的是的核心包之一包中的类。它执行的结果是:数据库内容得到更新,包括及其状态。
操作主要作用可以从下面方面来说明:
将集合进行格式化和过滤,消除其中的非法,并设定状态按照一定方法进行初始化分值;
将进行合并,消除重复的入口;
将及其状态、分值存入数据库,与原数据库中重复的则删除旧的,更换新的。
generate操作分析
操作调用的是包中的类。它执行的结果是:创建了抓取列表,存放于目录下,以时间为文件夹名称。循环抓取多少次,文件夹下就会有多少个以时间为名称的文件夹。
操作主要作用可以从下面方面来说明:
从数据库中将取出并进行过滤;
对进行排序,通过域名、链接数和一种算法综合进行降序排列;
将排列列表写入目录中。
fetch操作分析
操作调用的是包中的类。它执行的结果是:将页面内容抓取下来,存于目录下。
操作主要作用可以从下面方面来说明:
执行抓取,按照目录下的抓取列表进行;
抓取过程中,页面的地址可能因为链接发生改变,从而需要更新地址;
抓取采用多线程方式进行,以提高抓取速度;
操作过程中调用了操作。
parse操作分析
操作调用的是包中的类。它执行的结果是:将得到的页面解析为和,存于目录下。
操作主要作用可以从下面方面来说明:
解析中由得到的页面,并进行整理,将页面分成为和;
中保存的是页面的题名、作者、日期、链接等内容;
中保存的是页面的文本内容。
例如,我只执行一次抓取任务,就执行了上述的一些操作,操作的结果直接反映在目录中。可以看到在目录下面创建了这个目录,该目录中包含个目录:、、、、、,从目录名称就可以大致知道该目录存取的相关内容信息。
updatedb操作分析
操作调用的是包中的类。它执行的结果是:更新了数据库,为下一轮抓取做准备。
操作主要作用如下:
根据目录下目录和目录中的内容,对进行更新,增加新的,更换旧的。
invertlinks操作分析
操作用来更新,为建立索引的工作提供准备。
index过程分析
过程,即索引过程,包括:将数据转换成文本、分析文本、将分析过的文本保存到数据库中这三个操作。
转换成文本
在索引数据之前,首先必须将数据转换成能够处理的格式纯文本字符流。但是,在现实世界中,信息多以富媒体文档格式呈现:、、、、等。为此,采用了插件机制,通过各种各样的文档解析器,将富媒体转换成纯文字字符流。文档解析器种类繁多,开发人员可以根据需要进行选择,同时还可以自己修改或编写,非常灵活方便。
在对数据进行索引前,还需要进行预处理,对数据进行分析使之更加适合被索引。分析数据时,先将文本数据切分成一些大块或者语汇单元,然后对它们执行一些可选的操作,例如:在索引之前将这些语汇单元转换成小写,使得搜索对大小写不敏感;最有代表性的是要从输入中去掉一些使用很频繁但却没有实际意义的词,比如英文文本中的一些停止词、、、、等。同样的,我们也需要分析输入的语汇单元,以便从词语中去掉一些不必要的字母以找到它们的词干。这一处理过程称为分析。分析技术在索引和搜索时都会用到,比较重要。
将分析过的文本保存到数据库中
对输入的数据分析处理完成之后,就可以将结果写入到索引文件中。采用的是的索引格式,可以参考关于的索引机制。采用倒排索引的数据结果来存储索引的。
搜索程序分析
的搜索程序执行过程,可以从下面的步骤了解:
服务器接收用户发送过来的请求。对应到的运行代码中就是一个,称为查询处理器。查询处理器负责响应用户的请求,并将相应的结果页面返回给用户。
查询处理器对查询语句做一些微小的处理并将搜索的项转发到一组运行索引搜索器的机器上。的查询系统似乎比简单的多,这主要是因为搜索引擎的用户对他自己所要执行的查询内容有非常清晰的思路。然而,的系统结构非常灵活,且提供了多种不同的查询方式。看似简单的查询最终被转换为特定的查询类型。每个索引搜索器并行工作且返回一组有序的文档列表。
现在存在这大量从查询处理器返回过来的搜索结果数据流。查询处理器对这些结果集进行比较,从所有的结果查找出匹配最好的那些。如果其中任何一个索引搜索器在秒之后返回结果失败,该搜索器的结果将被忽略。因此,最后列表由操作成功的搜索器返回的结果组成。
关于查询处理器
查询处理器对查询作了一些细微的处理,例如删除停止词例如、等。接着需要执行一些操作以便于它在大规模的数据环境下能更好的工作。一个索引搜索器涉及搜索的文档集数目非常庞大,所以需要同时与很多索引搜索器交互来提高搜索速率。实际运行环境中,为了保证系统级别的稳定性,文档集的段文件会被复制到多个不同主机上。因为对于文档集中的每个段,查询处理器会随机的与其中一个可搜索到自身的索引搜索器相交互。如果发现一个索引搜索器不能交互,查询处理器会通知之后的搜索操作不使用该搜索器,但是查询处理器每隔一段时间会回头检查一次搜索器的状态,以防该主机上的搜索器再次可用。
关于分析器
使用自己的分析器,对应于包。把索引时进行分析所使用的二元语法技术与查询过程中对短语的优化技术结合在一起,通过二元语法技术可以把两个连续的词组合成一个语汇单元。这就可以大大减少搜索时需要考虑的文档范围,例如,包含词组的文档比包含的文档要少的多。
分析器对分析操作进行了封装。分析器通过执行若干操作,将文本语汇单元化,这些操作可能包括提取单词、去除标点符号、去掉语汇单元上的音调符号、将字母转化为小写也称为规格化、移除常用词、将单词转换为词干形式词干还原,或者将单词转换为基本形等。这个过程也称为语汇单元化过程。分析操作发生在两个阶段:建立索引和进行查询时。
的其他一些特性
为了获取小数量的文档通常是个左右,查询处理器会对每个索引搜索器进行查询。因为最后的结果是从多个索引搜索器中合并得到的,所以就没有必要从一个数据源中获取过多的文档结果,尤其是在用户很少去查看第一页之后的结果的情况下。
实际上,在每个用户查询被处理之前,它会被扩展为十分复杂的查询。每个索引过的文档都包含了三个域:网页自身的内容,网页的文本值,以及由所有关键文本所组成的合成文档,这些关键文本可在导航网页的超链接中找到。每个域对应一个不同的权重值。的查询处理器生成一个布尔查询,其中在三个域中都包含了搜索引擎用户所输入的文本。
也会特别的把那些在上出现的非常频繁的关键字组作为一个整体来索引其中的许多关键字是与相关的词组。这些关键字序列出现的非常频繁,所以无需花费精力去对这些词序中的每个组成部分单独搜索,也不必查找出这些搜索结果中是否有交集的部分。我们不用把这些项划分为单独的单词对来搜索文档,而是把它们作为一个单元,当然前提是在索引期间必须检测到它们是作为一个整体而存在的。另外,在与索引搜索器交互之前,查询处理器会查找出用户输入的字符串中单词的任意组合。如果这样一个词序确实存在,它的单词成员就会整合成一个特殊的搜索项。
在使用执行索引操作之前,的内容获取器索引器需要预处理文档。它使用解析器剥离中的内容,并索引其中的非标记文本。对于从文档提取标题文本,是很有建树的。
进程间通信层保持了查询处理器与索引搜索器间长时间的连接。查询处理器端可能存在多个并发的线程,对于给定的地址,任一线程都可以向远程服务器发送调用请求。服务器每接受一个请求之后,就会根据给定字符串尝试去查找对应的注册服务运行在自己线程上。客户端的请求线程会一直阻塞其他事件,直到服务器端响应的代码到达后,消息通知请求线程为止。如果服务器的响应花费的时间超过了规定的时限,的代码就会宣布此服务器不可用,并抛出一个异常。
另外,的排序算法是仿照的算法,关于算法的资料有很多,推荐《的秘密彻底解说中文版》。
支持分布式抓取,并有支持,可以进行多机分布抓取,存储和索引。另外很吸引人的一点在于,它提供了一种插件框架,使得其对各种网页内容的解析、各种数据的采集、查询、集群、过滤等功能能够方便的进行扩展,正是由于有此框架,使得的插件开发非常容易,第三方的插件也层出不穷,极大的增强了的功能和声誉。
的爬虫定制能力比较弱
,是 上的开源产品,出色之处在于它的可扩展性,可以扩展它的组件,来实现自定义的抓取逻辑,但配置比较复杂。在抓取中可以获取完整、精确的站点内容的复制。包括文本和非文本信息,抓取并存储内容,不对页面进行内容上的修改。在抓取速度上慢、需要大容量存储空间和宽速网络。重新爬行对相同的不进行替换。有控制管理界面,进行启动、监控。
的工作流程是一个循环,具体流程是:
  在预定的中选择一个。
  从选择的的网址下载远程文件
  分析,归档下载到的内容
  从分析到的内容里面选择感兴趣的。加入预定队列。
标记已经处理过的
(下载控制器)
整个下载过程的总的控制者,整个抓取工作的起点,决定整个抓取任务的开始和结束。从获取,传递给线程池()中的处理。
边界控制器
主要确定下一个将被处理的,负责访问的均衡处理,避免对某一服务器造成太大的压力。
它保存着的状态:
()发现的()
()正在被处理的()
()已经处理的()
是多线程的,每一个被一个处理。
下图为处理器的整个结构图
许多组成一个处理链()中每一个处理链对进行一系列的处理。
主要根据协议,以及下载范围控制信息判断当前是否应当处理。
(抓取处理链)
从远程服务器获取数据
(抽取处理链)
从网页中抽取新的
(写处理链)
负责把数据写入本地磁盘
(后置处理链)
由,,构成。
主要有三大部件:范围部件,边界部件,处理器链
范围部件:主要按照规则决定将哪个入队。
边界部件:跟踪哪个预定的将被收集,和已经被收集的,选择下一个,剔除已经处理过的。
处理器链:包含若干处理器获取,分析结果,将它们传回给边界部件
的其余部件有:
管理控制台:大多数都是单机的应用,内嵌服务器。操作者可以通过选择命令来操作控制台。
命令处理部件:包含足够的信息创建要爬的。
(处理器缓存):存放服务器的持久信息,能够被爬行部件随时查到,包括地址,历史记录,机器人策略。
处理器链:
预取链:主要是做一些准备工作,例如,对处理进行延迟和重新处理,否决随后的操作。
提取链:主要是获得资源,进行转换,填写请求和响应表单
抽取链:当提取完成时,抽取感兴趣的,,通常那里有新的也适合的,此时仅仅被发现,不会被评估
写链:存储爬行结果,返回内容和抽取特性,过滤完存储。
提交链:做最后的维护,例如,测试那些不在范围内的,提交给边界部件
包含以下关键特性:
用单个爬虫在多个独立的站点一直不断的进行递归的爬。
从一个提供的种子进行爬,收集站点内的精确,和精确主机。
主要是用广度优先算法进行处理。
主要部件都是高效的可扩展的
良好的配置,包括:
可设置输出日志,归档文件和临时文件的位置
可设置下载的最大字节,最大数量的下载文档,和最大的下载时间。
可设置工作线程数量。
可设置所利用的带宽的上界。
可在设置之后一定时间重新选择。
包含一些可设置的过滤机制,表达方式,路径深度选择等等。
的爬虫定制参数多
单实例的爬虫,之间不能进行合作。在有限的机器资源的情况下,却要复杂的操作。只有官方支持,仅仅在上进行了测试。每个爬虫是单独进行工作的,没有对更新进行修订。在硬件和系统失败时,恢复能力很差。很少的时间用来优化性能。
相对于,仅仅只是一个爬虫工具,没有提供搜索引擎。如果要对抓取的站点排序必须要实现类似于的复杂算法。
Web-Harvest
Web-Harvest是一个Java开源Web数据抽取工具。它能够收集指定的Web页面并从这些页面中提取有用的数据。Web-Harvest主要是运用了像XSLT,XQuery,正则表达式等这些技术来实现对text/xml的操作。
Crawler4j是一个开源的Java类库提供一个用于抓取Web页面的简单接口。可以利用它来构建一个多线程的Web爬虫。
Nutch与Heritrix比较
只获取并保存可索引的内容。则是照单全收。力求保存页面原貌
可以修剪内容,或者对内容格式进行转换。
保存内容为数据库优化格式便于以后索引;刷新替换旧的内容。而是添加追加新的内容。
从命令行运行、控制。有控制管理界面。
的定制能力不够强,不过现在已经有了一定改进。可控制的参数更多。
是个用来获取完整的、精确的、站点内容的深度复制。包括获取图像以及其他非文本内容。抓取并存储相关的内容。对内容来者不拒,不对页面进行内容上的修改。重新爬行对相同的不针对先前的进行替换。爬虫通过用户界面启动、监控、调整,允许弹性的定义要获取的。
支持分布式抓取,仅支持单机抓取,不能多机协同工作。
支持分布式爬取
考察垂直爬虫的几个原则:
性能较高:较好支持多线程并发处理;支持异步、非阻塞;支持分布式爬取;爬取调度算法性能较高;内存使用效率较高,不要老是出现问题;
架构优美:组件式设计式架构,扩展方便;架构设计精巧。至少值得花时间去学习架构设计思想。
扩展方便:能够与现有框架较好集成;由于是垂直爬虫,需要针对不同的网页定制爬取规则集逻辑,需要能够方便测试,不要老是重新编译,因此最好支持等脚本语言
功能全面:内置支持爬取、登录认证、深度爬取设置、页面压缩处理等
管理功能:提供爬虫管理接口,能够实时监控和管理爬取
调研结果:
如果开发一个基于或网页排序算法的搜索引擎,且不用对站点图片进行存储的搜索引擎可以用。本身就是一个网络搜索引擎解决方案,它分为抓取部分与搜索部分,并且实现了算法。
如果要开发一个可定制的、比较复杂的并要对站点进行深度复制,对网络资源进行长期保存的搜索引擎,可以使用。
个人感觉还是用比较好些。因为开发强度也比较小,如果仅仅只对某几个网站进行垂直搜索且对网站数据的排序只与检索词相关度有关不涉及,可以使用因为要在短时间实现算法并且成熟应用是比较困难的且本身不支持分布式抓取。
csdn_zuoqiang
浏览: 407769 次
来自: 深圳
这两个的差别可以看看这个文章,写的更加详细http://blo ...
已阅,我表示同意。
写的不错,挺详细的
&script&ale ...搜索引擎爬虫,抓取url的Java源码
-------------
新增文件夹...
新增文件夹
(多个标签用逗号分隔)
package se.
import java.io.IOE
import java.util.LinkedL
import java.util.L
import java.util.Q
import java.util.regex.M
import java.util.regex.P
import org.jsoup.J
import org.jsoup.nodes.D
import org.jsoup.nodes.E
import org.jsoup.select.E
public class Robot {
// robot url
private List&String& urlL
// cache url
private Queue&String& urlQ
// define Host
public final static String HOST = &debugs.tk&;
// constructor
public Robot() {
// initialization robot's member
setUrlList(new LinkedList&String&());
setUrlQueue(new LinkedList&String&());
public List&String& getUrlList() {
return urlL
public void setUrlList(List&String& urlList) {
this.urlList = urlL
public Queue&String& getUrlQueue() {
return urlQ
public void setUrlQueue(Queue&String& urlQueue) {
this.urlQueue = urlQ
// Legal link
private boolean isURL(String url) {
// judge url
Pattern pattern = pile(&^[a-zA-z]+://[^\\s]*&);
Matcher matcher = pattern.matcher(url);
if (matcher.matches()) {
} catch (Exception e) {
e.printStackTrace();
// whether the url is belong to host
public static boolean isHost(String url) {
return url.contains(HOST);
// travel all url
public void traverse(String seed) {
for (this.getUrlQueue().add(seed); !this.getUrlQueue().isEmpty();) {
boolean flag =
Document document =
document = Jsoup.connect(seed).timeout(5000).get();
} catch (IOException e) {
e.printStackTrace();
// whether connect success
// whether connect success,then select a tag
// add these aTag into queue
if (flag) {
// get url
Elements elements = document.select(&a[href]&);
for (Element e : elements) {
String s = e.attr(&abs:href&);
// Legal link and belong host
// and url not in list
// then add it
if (isURL(s) && s.contains(HOST)
&& (!getUrlQueue().contains(s))
&& (!getUrlList().contains(s))) {
this.getUrlQueue().add(s);
// get head of queue
// and set it seed
// travel seed it again
seed = this.getUrlQueue().poll();
this.getUrlList().add(seed);
// show information
// System.out.println(&SIZE:&
// + this.getUrlQueue().size() + &---&
// + seed + & connect!&);
// public static void main(String[] args) {
// Robot robot = new Robot();
// robot.traverse(&http://debugs.tk&);
// List&String& list = robot.getUrlList();
// for (String s : list) {
// System.out.println(s);
相关资讯  — 
相关文档  — 
发布时间: 15:27:28
同类热门经验
20246次浏览
24040次浏览
17799次浏览
15546次浏览
19275次浏览
11756次浏览
OPEN-OPEN, all rights reserved.

我要回帖

更多关于 网络爬虫源代码 的文章

 

随机推荐