2 宽度优先爬虫和带偏好的爬虫(4)
5 Java带偏好的爬虫示例
在上一节中,我们已经指出,可以使用优先级队列(PriorityQueue)来实现这个带偏好的爬虫。在深入讲解之前,我们首先介绍优先级队列。
优先级队列是一种特殊的队列,普通队列中的元素是先进先出的,而优先级队列则是根据进入队列中的元素的优先级进行出队列操作。例如操作系统的一些优先级进程管理等,都可以使用优先级队列。优先级队列也有最小优先级队列和最大优先级队列两种。
理论上,优先级队列可以是任何一种数据结构,线性的和非线性的,也可以是有序的或无序的。针对有序的优先级队列而言,获取最小或最大的值是非常容易的,但是插入却非常困难;而对于无序的有衔接队列而言,插入是很容易的,但是获取最大和最小值是很麻烦的。根据以上的分析,可以使用“堆”这种折中的数据结构来实现优先级队列。
从JDK1.5开始,Java提供了内置的支持优先级队列的数据结构——java.util.PriorityQueue。
我们在上边的代码中,只要稍微修改一下,就可以支持从URL队列中选择优先级高的URL。
LinkQueue类:
1 public class LinkQueue{ 2 //已访问的URL集合 3 private static Set visitedUrl=new HashSet(); 4 //待访问的URL集合 5 private static Queueun VisitedUrl=new PriorityQueue(); 6 //获得URL队列 7 public static Queue getUnVisitedUrl(){ 8 return unVisitedUrl; 9 } 10 //添加到访问过的URL队列中 11 public static void addVisitedUrl(String url){ 12 visitedUrl.add(url); 13 } 14 //移除访问过的URL 15 public static void removeVisitedUrl(String url){ 16 visitedUrl.remove(url); 17 } 18 //未访问的URL出队列 19 public static Object unVisitedUrlDeQueue(){ 20 return unVisitedUrl.poll(); 21 } 22 //保证每个URL只被访问一次 23 public static void addUnvisitedUrl(String url){ 24 if(url!=null && !url.trim().equals("") 25 &&!visitedUrl.contains(url) 26 &&!unVisitedUrl.contains(url)) 27 unVisitedUrl.add(url); 28 } 29 //获得已经访问的URL数目 30 public static int getVisitedUrlNum(){ 31 return visitedUrl.size(); 32 } 33 //判断未访问的URL队列中是否为空 34 public static boolean unVisitedUrlsEmpty(){ 35 return unVisitedUrl.isEmpty(); 36 } 37 }
在带偏好的爬虫里,队列元素的优先级是由URL的优先级确定的。关于如何确定URL的优先级,有一些专用的链接分析的方法,比如Google的PageRank和HITS算法。