【搜索引擎Jediael开发笔记】V0.1完整代码 2014-05-26 15:16 443人阅读 评论(0) 收藏
详细代码请见
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();
}
} }
版权声明:本文为博主原创文章,未经博主允许不得转载。
【搜索引擎Jediael开发笔记】V0.1完整代码 2014-05-26 15:16 443人阅读 评论(0) 收藏的更多相关文章
- 【搜索引擎Jediael开发笔记】v0.1完整代码 2014-05-26 15:17 463人阅读 评论(0) 收藏
详细代码请见 E:\Project\[重要]归档代码\SearchEngine归档代码 或 https://code.csdn.net/jediael_lu/jediael/tree/10991c83 ...
- Latex笔记(参考文献) 分类: LaTex 2014-11-08 17:41 239人阅读 评论(0) 收藏
当你用LaTeX来写文档,在管理参考文献时,你可能会用到bibtex, 也许你会嫌麻烦,会选择用 \begin{thebibliography}{10} \bibitem xxxx \bibitem ...
- shell入门之变量测试 分类: 学习笔记 linux ubuntu 2015-07-10 15:49 31人阅读 评论(0) 收藏
格式:test 测试条件 字符串测试: 注意空格: test str1 == str2 测试字符串是否相等 test str1 != str2 测试字符串是否不相等 test str1 测试字符串是否 ...
- 公众号第三方平台开发 获取 component_verify_ticket 2015-07-05 10:16 59人阅读 评论(0) 收藏
8.推送component_verify_ticket协议 在公众号第三方平台创建审核通过后,微信服务器会向其"授权事件接收URL"每隔10分钟定时推送component_veri ...
- 使用Broadcast实现android组件之间的通信 分类: android 学习笔记 2015-07-09 14:16 110人阅读 评论(0) 收藏
android组件之间的通信有多种实现方式,Broadcast就是其中一种.在activity和fragment之间的通信,broadcast用的更多本文以一个activity为例. 效果如图: 布局 ...
- ubuntu常用文件搜索命令 分类: linux 学习笔记 ubuntu 2015-07-05 15:40 84人阅读 评论(0) 收藏
1.find find [搜索路径] [搜索关键字] 比如查找/test中文件名为t5.tmp的文件: 查找根目录下大于100M的文件 注意,这里的204800单位是块,1块=512字节 在根目录下查 ...
- shell脚本实现冒泡排序 分类: 学习笔记 linux ubuntu 2015-07-10 14:16 79人阅读 评论(0) 收藏
手动输入一行字符串,并对其排序. 脚本如下: #!/bin/bash #a test about sort echo "please input a number list" re ...
- iOS开发 调用系统相机和相册 分类: ios技术 2015-03-30 15:52 65人阅读 评论(0) 收藏
调用系统相机和相册 (iPad,iPhone) 打开相机:(iPad,iPhone) //先设定sourceType为相机,然后判断相机是否可用(ipod)没相机,不可用将sourceType设定为 ...
- 架构师速成6.7-设计开发思路-uml 分类: 架构师速成 2015-07-29 18:25 157人阅读 评论(0) 收藏
uml是什么东西?统一建模语言,一门语言,是用来进行软件设计的一门语言. 其实一门语言的诞生并不伟大,让大多数人都使用才足够伟大.uml就是一门伟大的语言,因为目前软件设计的唯一语言就是它. UML其 ...
随机推荐
- 单位阶跃函数(Heaviside/unit step function)—— 化简分段函数
注意,单位阶跃函数一种不连续函数. 1. 常见定义 最经典的定义来自于 Ramp function(斜坡函数,max{x,0})的微分形式: H(x)=ddxmax{x,0} 2. 化简分段函数 如对 ...
- 1.3 Quick Start中 Step 8: Use Kafka Streams to process data官网剖析(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Step 8: Use Kafka Streams to process data ...
- carousel轮播器
<div id="myCarousel" class="carousel slide" data-ride="carousel" st ...
- THC=TERMINAL HANDLING CHARGE,碼頭操作費
THC=TERMINAL HANDLING CHARGE,碼頭操作費
- BZOJ3514: Codechef MARCH14 GERALD07加强版(LCT,主席树)
Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M ...
- 【习题 7-4 UVA-818】Cutting Chains
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 二进制枚举要解开哪些环. 把所有和它相关的边都删掉. 对于剩下的联通分量. 看看是不是每一个联通分量都是一条链 ->每个点的度 ...
- jsp中标签id和name的区别(转)
name原来是为了标识之用,但是现在根据规范,都建议用id来标识元素. 但是name在以下用途是不能替代的:1. 表单(form)的控件名,提交的数据都用控件的name而不是id来控制.因为有许多na ...
- IntelliJ IDEA 2018 Community(社区版)创建J2EE项目+Tomcat9部署
博主打算开始系统地自学JAVA,首要问题就是解决IDE的问题, 以前用过像VS.Android Studio.Eclipse,知道Eclipse是JAVA最传统的IDE, 用过VS和AS的朋友都知道, ...
- C++ Traits 技术
Tarits.特性的复数. c++萃取技术就是指它. 实现方式是模板特化. STL中涉及到iterator的地方常常能用到它. gcc的STL与VS的STL略有区别. vs中下列代码,把鼠标放在ite ...
- 关于hadoop hdfs里文件为啥上一级大小是0,进去又有大小问题解释?
问题 好像跟平时的理解不一样,外边是0,进去就是有大小了? 答:hdfs具体文件是针对具体文件的,不是文件目录. 文件夹大小为0,不是里面所有内容为0.