zoukankan      html  css  js  c++  java
  • 【搜索引擎Jediael开发笔记】V0.1完整代码

    详细代码请见

    E:Project【重要】归档代码SearchEngine归档代码

    https://code.csdn.net/jediael_lu/jediael/tree/10991c839c51d32f825708b09451b2618a20ee94

    http://download.csdn.net/detail/jediael_lu/7402827


    本版本完成以下功能:

    (1)创建用于保存种子URL的配置文件及其数据结构

    (2)创建用于保存Todo信息(未下载URL)的数据结构

    (3)创建用于保存Visited信息(已下载的URL)的数据结构

    (4)下载网页时同步更新Tode与Visited。下载网页前,判断某个网页是否已经下载过。

    (5)从上述第3步下载的网页抽取链接并继续下载,直到Todo列表为空。

    (6)为每个种子url创建一个独立的线程。

    至此,搜索引擎已具体基本功能。


    下一阶段工作:

    (1)引入dao,使用数据库保存一些信息,如种子url等?

    (2)使用Berkey DB保存Frontier?使用布隆过滤器保存已访问的url。

    (3)继续学习后面内容,引入其它内容。如访问blog.csdn.net时,返回403。


    1、创建用于保存种子url的数据结构

    由于一般而言,种子url的数据量均小,因此先使用PriorityQueue,以图方便,今后视应用情况修改成其它数据结构。

    package org.ljh.search.frontier;
    
    import java.util.PriorityQueue;
    
    public class SeekUrlQueue {
    <span style="white-space:pre">	</span>
    <span style="white-space:pre">	</span>//保存种子url的队列。由于一般而言,种子url的数据量均小,因此先使用PriorityQueue,以图方便,今后视应用情况修改成其它数据结构。
    <span style="white-space:pre">	</span>private PriorityQueue<String> seekUrlQueue = new PriorityQueue<String>();
    
    
    <span style="white-space:pre">	</span>//Getter
    <span style="white-space:pre">	</span>public PriorityQueue<String> getSeekUrlQueue() {
    <span style="white-space:pre">		</span>return seekUrlQueue;
    <span style="white-space:pre">	</span>}
    <span style="white-space:pre">	</span>
    <span style="white-space:pre">	</span>//将url添加至种子url队列中
    <span style="white-space:pre">	</span>public boolean add(String url){
    <span style="white-space:pre">		</span>return seekUrlQueue.add(url);
    <span style="white-space:pre">	</span>}
    
    <span style="white-space:pre">	</span>//判断种子url队列是否为空
    <span style="white-space:pre">	</span>public boolean isEmpty(){
    <span style="white-space:pre">		</span>return seekUrlQueue.isEmpty();
    <span style="white-space:pre">	</span>}
    <span style="white-space:pre">	</span>
    <span style="white-space:pre">	</span>//从种子url队列中获取下一个种子url
    <span style="white-space:pre">	</span>public String getNext(){
    <span style="white-space:pre">		</span>return seekUrlQueue.poll();
    <span style="white-space:pre">	</span>}<span style="white-space:pre">	</span>
    }
    

    2、创建用于保存已访问url的数据结构

    (1)先创建一个接口,用于提供最基本功能

    package org.ljh.search.frontier;
    
    public interface VisitedUrlQueue {
    	
    	//判断某个Url是否已经存在于已访问队列中
    	public  boolean contains(String url);
    	
    	//将已下载的url放入已访问的列表
    	public boolean add(String url);
    
    }
    

    (2)创建具体的实施类

    package org.ljh.search.frontier;
    
    import java.util.HashSet;
    
    public class HashSetVisitedUrlQueue implements VisitedUrlQueue{
    	
    	//用于保存已访问的Url的数据结构。由于已访问列表会被经常查询,因此,使用HashSet。由于只要其中任何一个线程下载过,此url即算做已经下载,因此使用了static。
    	private static HashSet<String> visitedUrlQueue = new HashSet<String>();
    
    	public HashSet<String> getVisitedUrlQueue() {
    		return visitedUrlQueue;
    	}
    
    	@Override
    	public boolean contains(String url) {
    		return visitedUrlQueue.contains(url);
    	}
    
    	@Override
    	public boolean add(String url) {
    		visitedUrlQueue.add(url);
    		return true;
    	}
    }
    

    3、创建待访问的url列表的数据结构

    (1)先创建接口

    package org.ljh.search.frontier;
    
    public interface Frontier {
    	//获取下一个待访问的url
    	public String getNextUrl();
    	
    	//将从其它网页中提取出来的url放到待访问url中。
    	public boolean putUrlIntoTodoQueue(String url);
    
    }

    (2)创建具体实现类

    package org.ljh.search.frontier;
    
    import java.util.PriorityQueue;
    
    public class PriorityQueueFrontier implements Frontier {
    	
    	//保存待访问的url的列表。考虑到先入先出及可在一定程度上控制访问顺序,即带偏好的宽度优先搜索策略,使用了PriorityQueue。
    	private PriorityQueue<String> todoUrlQueue = new PriorityQueue<String>();
    
    	@Override
    	public String getNextUrl() {
    		return todoUrlQueue.poll();
    	}
    
    	@Override
    	public boolean add(String url) {
    		todoUrlQueue.add(url);
    		return true;
    	}
    	
    	@Override
    	public boolean isEmpty(){
    		return todoUrlQueue.isEmpty();
    	}
    
    }
    

    4、修改主类

    (1)下载网页前,判断某个网页是否已经下载过。

    (2)分析刚下载的网页,提取链接,继续放入frontier。

    (3)为每个种子url创建一个独立的线程。

    package org.ljh.search;
    
    import java.io.IOException;
    import java.util.Iterator;
    import java.util.Set;
    
    import org.ljh.search.downloadpage.PageDownloader;
    import org.ljh.search.frontier.HashSetVisitedUrlQueue;
    import org.ljh.search.frontier.PriorityQueueFrontier;
    import org.ljh.search.frontier.SeekUrlQueue;
    import org.ljh.search.html.HtmlParserTool;
    import org.ljh.search.html.LinkFilter;
    
    public class MyCrawler {
    
    	public static void main(String[] args) {
    
    		// 种子url
    		final SeekUrlQueue seekUrlQueue = new SeekUrlQueue();
    		seekUrlQueue.add("http://www.sohu.com");
    		seekUrlQueue.add("http://www.baidu.com");
    		seekUrlQueue.add("http://www.eoeandroid.com/");
    		
    		// 已访问过的url
    		final HashSetVisitedUrlQueue visitedUrl = new HashSetVisitedUrlQueue();
    
    		// 设定过滤器,用于指明搜索范围
    		final LinkFilter linkFilter = new LinkFilter() {
    			@Override
    			public boolean accept(String url) {
    				if ((url.contains("baidu") || url.contains("sohu")||url.contains("eoe"))
    						&& !url.contains("baike") && !url.contains("@")) {
    					return true;
    				} else {
    					return false;
    				}
    			}
    		};
    
    		while (!seekUrlQueue.isEmpty()) {
    
    			// 根据种子url对frontier进行初始化
    			final String nextSeek = seekUrlQueue.getNext();
    			System.out.println(nextSeek);
    
    			//为每一个种子url,启动一个线程
    			Thread t = new Thread(new Runnable() {
    				@Override
    				public void run() {
    					// 待访问 的url
    					PriorityQueueFrontier frontier = new PriorityQueueFrontier();
    					frontier.add(nextSeek);
    					
    					//直到frontier为空,才会结束下载
    					while (!frontier.isEmpty()) {
    						//获取下一个待访问的url,然后判断是否已经访问过,若否,则下载,并将其添加到已访问列表。
    						String nextUrl = frontier.getNextUrl();
    						if (!visitedUrl.contains(nextUrl)) {
    							try {
    								PageDownloader.downloadPageByGetMethod(nextUrl);
    							} catch (IOException e) {
    								e.printStackTrace();
    							}
    							visitedUrl.add(nextUrl);
    							
    							//从刚下载的页面中提取链接,并将其放入frointier.正常而言,应该使用刚下载到本地的文件作参数,但此处还是使用了url,会导致再一次连接网络。
    							Set<String> urlSet = HtmlParserTool.extractLinks(
    									nextUrl, linkFilter);
    							Iterator<String> iterator = urlSet.iterator();
    							while (iterator.hasNext()) {
    								frontier.add(iterator.next());
    							}
    						}
    					}
    				}
    
    			});
    
    			t.start();
    		}
    	}
    
    }
    





  • 相关阅读:
    BZOJ 1040 (ZJOI 2008) 骑士
    BZOJ 1037 (ZJOI 2008) 生日聚会
    ZJOI 2006 物流运输 bzoj1003
    ZJOI 2006 物流运输 bzoj1003
    NOI2001 炮兵阵地 洛谷2704
    NOI2001 炮兵阵地 洛谷2704
    JLOI 2013 卡牌游戏 bzoj3191
    JLOI 2013 卡牌游戏 bzoj3191
    Noip 2012 day2t1 同余方程
    bzoj 1191 [HNOI2006]超级英雄Hero——二分图匹配
  • 原文地址:https://www.cnblogs.com/jediael/p/4304135.html
Copyright © 2011-2022 走看看