详细代码请见

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 {

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

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();
}
} }

 

 

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

【搜索引擎Jediael开发笔记】v0.1完整代码 2014-05-26 15:17 463人阅读 评论(0) 收藏的更多相关文章

  1. 【搜索引擎Jediael开发笔记】V0.1完整代码 2014-05-26 15:16 443人阅读 评论(0) 收藏

    详细代码请见 E:\Project\[重要]归档代码\SearchEngine归档代码 或 https://code.csdn.net/jediael_lu/jediael/tree/10991c83 ...

  2. shell入门之变量测试 分类: 学习笔记 linux ubuntu 2015-07-10 15:49 31人阅读 评论(0) 收藏

    格式:test 测试条件 字符串测试: 注意空格: test str1 == str2 测试字符串是否相等 test str1 != str2 测试字符串是否不相等 test str1 测试字符串是否 ...

  3. ubuntu常用文件搜索命令 分类: linux 学习笔记 ubuntu 2015-07-05 15:40 84人阅读 评论(0) 收藏

    1.find find [搜索路径] [搜索关键字] 比如查找/test中文件名为t5.tmp的文件: 查找根目录下大于100M的文件 注意,这里的204800单位是块,1块=512字节 在根目录下查 ...

  4. iOS开发 调用系统相机和相册 分类: ios技术 2015-03-30 15:52 65人阅读 评论(0) 收藏

     调用系统相机和相册 (iPad,iPhone) 打开相机:(iPad,iPhone) //先设定sourceType为相机,然后判断相机是否可用(ipod)没相机,不可用将sourceType设定为 ...

  5. 架构师速成6.7-设计开发思路-uml 分类: 架构师速成 2015-07-29 18:25 157人阅读 评论(0) 收藏

    uml是什么东西?统一建模语言,一门语言,是用来进行软件设计的一门语言. 其实一门语言的诞生并不伟大,让大多数人都使用才足够伟大.uml就是一门伟大的语言,因为目前软件设计的唯一语言就是它. UML其 ...

  6. 【搜索引擎Jediael开发4】V0.01完整代码 分类: H_HISTORY 2014-05-21 21:35 470人阅读 评论(0) 收藏

    截止目前,已完成如下功能: 1.指定某个地址,使用HttpClient下载该网页至本地文件 2.使用HtmlParser解释第1步下载的网页,抽取其中包含的链接信息 3.下载第2步的所有链接指向的网页 ...

  7. vs2008 多人同时开发项目时的代码注释规范格式 分类: C#小技巧 2014-04-23 14:12 297人阅读 评论(0) 收藏

    多人同时开发一个项目,区分项目的那个窗体是谁开发的,例:下面的格式 /************************************************       模块:服务器设置   ...

  8. android开发之调试技巧 分类: android 学习笔记 2015-07-18 21:30 140人阅读 评论(0) 收藏

    我们都知道,android的调试打了断点之后运行时要使用debug as->android application 但是这样的运行效率非常低,那么我们有没有快速的方法呢? 当然有. 我们打完断点 ...

  9. 善用VS中的Code Snippet来提高开发效率 分类: C# 2015-01-22 11:06 69人阅读 评论(0) 收藏

    前言  在谈谈VS中的模板中,我介绍了如何创建项目/项模板,这种方式可以在创建项目时省却不少重复性的工作,从而提高开发效率.在创建好了项目和文件后,就得开始具体的编码了,这时又有了新的重复性工作,就是 ...

随机推荐

  1. [Java开发之路](16)学习log4j日志

    1. 新建一个Javaproject.导入Jar包(log4j-1.2.17.jar) Jar包下载地址:点击打开链接 2. 配置文件:创建并设置log4j.properties # 设置 log4j ...

  2. 探索Oracle之数据库升级八 12c Downgrade 11gR2

    探索Oracle之数据库升级八 12c Downgrade 11gR2 前言: 我们前面已经完毕了11gR2 upgrade to 12c 的升级,整个过程还是比較顺利的,尽管和曾经版本号升级有些不太 ...

  3. eclipse- DDMS截图功能使用

    如何使用eclipse的截图功能呢 1.打开eclipse 2.连接手机 3.打开eclipse的DDMS插件. 4.选中手机 5.点击上面的摄像机图标,就可以截图了 如果你打开了DDMS以后,没有发 ...

  4. 洛谷——P1012 拼数

    https://www.luogu.org/problem/show?pid=1012#sub 题目描述 设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数. 例如:n=3时,3个整 ...

  5. 【转载】使用logstash+elasticsearch+kibana快速搭建日志平台

    原文链接:http://www.cnblogs.com/buzzlight/p/logstash_elasticsearch_kibana_log.html 日志的分析和监控在系统开发中占非常重要的地 ...

  6. adapter-自定义adapter的典型写法

    文章参考 http://www.cnblogs.com/mengdd/p/3254323.html import android.content.Context; import android.vie ...

  7. Android时间对话框TimePickerDialog介绍

    目前网上流行着很多对“时间对话框TimePickerDialog”的讲解文章,但感觉都不是很详细.这里详细对该方面的知识进行介绍,旨在帮助初学者能够快速掌握该项技术. 首先要做的是声明一个日历类的对象 ...

  8. Vue使用Promise自定义confirm确认框组件

    使用Promise模拟浏览器确认框,可自定义标题,内容,按钮文字和类型 参数名 类型 说明 title String 标题 content String 内容 yesBtnText String 确认 ...

  9. .vsdc和.svf用于formal verification tools

    svf:Setup Verification for Formality

  10. 【“玲珑杯”ACM比赛 Round #20 H】康娜的数学课

    [链接]http://www.ifrog.cc/acm/problem/1161 [题意] 在这里写题意 [题解] 首先x<l肯定无解; 然后,肯定是要选其中的一些数字的. 而且这些数字肯定是大 ...