【搜索引擎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 {//保存種子url的隊列。由于一般而言,種子url的數據量均小,因此先使用PriorityQueue,以圖方便,今后視應用情況修改成其它數據結構。private PriorityQueue<String> seekUrlQueue = new PriorityQueue<String>();//Getterpublic PriorityQueue<String> getSeekUrlQueue() {return seekUrlQueue;}//將url添加至種子url隊列中public boolean add(String url){return seekUrlQueue.add(url);}//判斷種子url隊列是否為空public boolean isEmpty(){return seekUrlQueue.isEmpty();}//從種子url隊列中獲取下一個種子urlpublic 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;}@Overridepublic boolean contains(String url) {return visitedUrlQueue.contains(url);}@Overridepublic boolean add(String url) {visitedUrlQueue.add(url);return true;} }
3、創建待訪問的url列表的數據結構
(1)先創建接口
package org.ljh.search.frontier;public interface Frontier {//獲取下一個待訪問的urlpublic 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>();@Overridepublic String getNextUrl() {return todoUrlQueue.poll();}@Overridepublic boolean add(String url) {todoUrlQueue.add(url);return true;}@Overridepublic 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) {// 種子urlfinal SeekUrlQueue seekUrlQueue = new SeekUrlQueue();seekUrlQueue.add("http://www.sohu.com");seekUrlQueue.add("http://www.baidu.com");seekUrlQueue.add("http://www.eoeandroid.com/");// 已訪問過的urlfinal HashSetVisitedUrlQueue visitedUrl = new HashSetVisitedUrlQueue();// 設定過濾器,用于指明搜索范圍final LinkFilter linkFilter = new LinkFilter() {@Overridepublic 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() {@Overridepublic void run() {// 待訪問 的urlPriorityQueueFrontier 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完整代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于serialVersionUID的说
- 下一篇: 【Heritrix基础教程之1】在Ecl