当前位置: 移动技术网 > IT编程>开发语言>Java > Java应用开源框架实现简易web搜索引擎

Java应用开源框架实现简易web搜索引擎

2019年07月19日  | 移动技术网IT编程  | 我要评论

引言

应用 java 的开源库,编写一个搜索引擎,这个引擎能爬取一个网站的内容。并根据网页内容进行深度爬取,获取所有相关的网页地址和内容,用户可以通过关键词,搜索所有相关的网址。

具体功能

(1) 用户可以指定爬取一个url对应的网页的内容。
(2) 对网页内容进行解析,并获取其中所有的url链接地址。
(3) 用户可以设定爬取深度,代表着从初始url对应的页面开始,可以爬取其中所有的url对应的网页内的url,以此类推。深度越大,能爬取到的网站越多。
(4) 对爬取到的url内容进行保存、建立索引。建立索引的内容是url地址本身,和url对应的网页标题。
(5) 用户可以通过关键词对网址进行搜索,找出有该关键词的url地址。
(6) 建立索引和搜索索引的过程能智能识别中文关键词,能对关键词进行分词操作。
(7) 用户可以指定保存索引的地址、初始url、爬取深度、进行搜索的关键词和最大匹配项。

开源框架

  1. lucene
  2. jsoup

源码

爬虫部分:spider.java

package webcrawler.spider;

import java.io.ioexception;
import java.util.arraylist;
import java.util.hashset;
import java.util.scanner;

import org.jsoup.jsoup;
import org.jsoup.nodes.document;
import org.jsoup.nodes.element;
import org.jsoup.select.elements;

import webcrawler.index.buildindex;

/**
 * @author lannooo
 */

public class spider {
  arraylist<string> urls;
  private string starturl;
  private int diglevel;

  /**
   * @param starturl 爬虫的起始url
   * @param diglevel 爬取深度
   */
  public spider(string starturl, int diglevel){
    this.starturl = starturl;
    this.diglevel = diglevel;
    this.urls = new arraylist<>();
  }

  /**
   * @param level 当前爬取的深度剩余
   * @param arraylist 需要进行下一轮爬去的url集
   * @return 从一格url集爬取到的新的url集
   * @throws ioexception
   */
  public arraylist<string> getlevelurls(int level, arraylist<string> arraylist) 
      throws ioexception{
    arraylist<string> total = null;
    if(level>0){      
      total = new arraylist<>();
      for(string url: arraylist){
        /*对于每个arraylist中的url,首先解析其网页内容,并获得里面所有url项*/
        for(string each: getbarelinks(url)){
          total.add(each);
        }
      }
      /*用hashset这个容器将total里面重复项删除*/
      hashset<string> hashset = new hashset<>(total);
      total = new arraylist<>(hashset);
    }
    return total;
  }

  /**
   * 从starturl开始,爬取所有相关urls
   * @throws ioexception
   */
  public void getall() throws ioexception{
    arraylist<string> newurls;
    arraylist<string> currenturls = new arraylist<>();
    /*把starturl加入currenturls这个列表中,从这个url开始爬*/
    currenturls.add(starturl);
    for(int i=diglevel; i>0; i--){
      /*
       * 对于每一层,都要获取一次由这个url引申出去的url集
       * 然后把当前集的已经爬去过的url加入到总的url集中
       * 最后newurls作为新的需要进行深度爬取的集进入下一轮循环
       */
      system.out.println("dig into level: " + (diglevel-i+1));
      newurls = getlevelurls(i, currenturls);
      for(string each: currenturls){
        urls.add(each);
      }
      currenturls = newurls;
    }
    for(string each:currenturls){
      urls.add(each);
    }
    hashset<string> hashset = new hashset<>(urls);
    urls = new arraylist<>(hashset);
  }

  /**
   * @param path 保存索引的路径
   * @throws ioexception
   */
  public void storeurlsandinfo(string path) throws ioexception{
    buildindex build = new buildindex(path);
    /* 把urls中的所有url进行实际网页标题的爬取*/
    for(string each:urls){
      string text = getlinktext(each);
      if(text!=null){
        build.addfield("url", each);
        build.addfield("text", text);
        /*将这一个entry加入索引中*/
        build.pushindex();
      }
    }
    build.close();
  }

  /**
   * @param url 需要获取网页标题的url
   * @return 标题内容
   * @throws ioexception
   */
  public string getlinktext(string url) throws ioexception{
    document document = null;
    try {
      /*用jsoup进行连接,设置超时时间为3秒*/
      document = jsoup.connect(url).timeout(3000).get();
    } catch (exception e) {
      system.out.println("[timeout]get title of url:"+url);
      return null;
    }
    string title = document.title();
    return title;
  }


  /**
   * @param url 进行内容解析的url
   * @return 返回该url的网页内容内的所有urls列表
   * @throws ioexception
   */
  public arraylist<string> getbarelinks(string url) throws ioexception{
    arraylist<string> linkslist = new arraylist<>();
    document document;

    try {
      document = jsoup.connect(url).timeout(2000).get();
    } catch (exception e) {
      return linkslist;
    }
    /*获取<body>标签理的所有带href属性的<a>标签*/
    elements links = document.select("body").select("a[href]");

    for(element link: links){
      /*从每一个解析得到的<a>标签中提取url,并去除锚点*/
      string href = link.attr("abs:href").replaceall("#", "");
      /*只添加含有zju.edu.cn字符的url,去除末尾的'/'*/
      if(href.contains("zju.edu.cn")){
        if (href.endswith("/")){
          href = href.substring(0, href.length()-1);
        }
        linkslist.add(href);
      }
    }
    hashset<string> hashset = new hashset<>(linkslist);
    arraylist<string> arraylist = new arraylist<>(hashset);

    return arraylist;
  }

  public static void main(string[] args) {
    scanner in = new scanner(system.in);
    system.out.println("enter url:");
    string url = in.nextline().trim();
    while(!url.startswith("http://")){
      system.out.println("http:// is needed!");
      system.out.println("enter url:");
      url = in.nextline().trim();
    }
    system.out.println("enter depth to dig more urls[<=3 recommended]:");
    int depth = in.nextint();
    spider spider = new spider(url, depth);
    system.out.println("enter path you want to save[default=d:/index-spider]:");
    string path = in.nextline().trim();
    if(path.length()==0){
      path = "d:/index-spider";
    }
    try {
      system.out.println("start fetching...");
      spider.getall();
      system.out.println("urls got success!");
      spider.storeurlsandinfo(path);
      system.out.println("stored success!");
    } catch (ioexception e) {
      e.printstacktrace();
    }
  }

 
}

建立索引:buildindex.java

package webcrawler.index;

import java.io.*;

import org.apache.lucene.analysis.analyzer;
import org.apache.lucene.document.document;
import org.apache.lucene.document.field;
import org.apache.lucene.document.textfield;
import org.apache.lucene.index.indexwriter;
import org.apache.lucene.index.indexwriterconfig;
import org.apache.lucene.store.directory;
import org.apache.lucene.store.fsdirectory;
import org.apache.lucene.util.version;
import org.wltea.analyzer.lucene.ikanalyzer;

/**
 * @author lannooo
 *
 */
public class buildindex {
  private file file;
  private directory directory;
  private indexwriter indexwriter;
  private indexwriterconfig config;
  private analyzer analyzer;
  private document document;

  /**
   * @param path 建立索引的路径
   */
  public buildindex(string path) {
    try {
      file = new file(path);
      directory = fsdirectory.open(file);
      document = new document();
      analyzer = new ikanalyzer();    /*中文分词工具类*/
      config = new indexwriterconfig(version.lucene_4_10_0, analyzer);
      indexwriter = new indexwriter(directory, config);      

    } catch (exception e) {
      e.printstacktrace();
    }
  }

  /**
   * @param fieldname 加入到document中的新的一项的名称
   * @param fieldtext 新的一项的内容
   */
  public void addfield(string fieldname, string fieldtext){
    try{
      field field = new textfield(fieldname, fieldtext, field.store.yes);
      document.add(field);
    }catch (exception e) {
      e.printstacktrace();
    }
  }

  /**
   * 将document加入到索引中
   */
  public void pushindex(){
    try {
      indexwriter.adddocument(document);
      document = new document();
    } catch (exception e) {
      e.printstacktrace();
    }
  }

  /**
   * 加入完整的一个document并保存到索引中
   * @param url 加入的url地址
   * @param text url对应的文本
   */
  public void addoneindex(string url, string text){
    this.addfield("url", url);
    this.addfield("text", text);
    this.pushindex();
  }

  /**
   * 关闭索引写入
   */
  public void close(){
    try {
      indexwriter.close();
    } catch (exception e) {
      e.printstacktrace();
    }
  }

}

搜索索引

package webcrawler.index;

import java.io.file;
import java.util.scanner;

import org.apache.lucene.analysis.analyzer;
import org.apache.lucene.document.document;
import org.apache.lucene.index.directoryreader;
import org.apache.lucene.queryparser.classic.queryparser;
import org.apache.lucene.search.indexsearcher;
import org.apache.lucene.search.query;
import org.apache.lucene.search.scoredoc;
import org.apache.lucene.search.topdocs;
import org.apache.lucene.store.fsdirectory;
import org.wltea.analyzer.lucene.ikanalyzer;

/**
 * @author lannooo
 *
 */
public class searchindex {
  private indexsearcher indexsearcher;
  private analyzer analyzer;
  private queryparser parser;
  private query query;
  private topdocs hits;
  private directoryreader reader;

  /**
   * @param path 进行索引搜索的路径
   */
  public searchindex(string path){
    try {
      reader = directoryreader.open(fsdirectory.open(new file(path)));
      indexsearcher = new indexsearcher(reader);
      analyzer = new ikanalyzer();
    } catch (exception e) {
      e.printstacktrace();
    }
  }

  /**
   * @param fieldname 搜索的域名称
   * @param text 搜索的内容
   * @param matchnumber 最大匹配项数
   * @return 搜索到的最大匹配数
   */
  public int search(string fieldname, string text, int matchnumber){
    try {
      parser = new queryparser(fieldname, analyzer);
      query = parser.parse(text);
      hits = indexsearcher.search(query, matchnumber);

      return hits.totalhits;
    } catch (exception e) {
      e.printstacktrace();
    }
    return -1;
  }
  /**
   * 打印所有的匹配项
   */
  public void printhits(){
    try{
      system.out.println("total hits number:"+hits.totalhits);
      for(scoredoc doc: hits.scoredocs){
        document document = indexsearcher.doc(doc.doc);
        system.out.println(document.get("url"));
        system.out.println(document.get("text"));
      }
      reader.close();
    }catch (exception e) {
      e.printstacktrace();
    }
  }
  public static void main(string[] args) {
    /*输入关键词*/
    scanner in = new scanner(system.in);
    system.out.println("enter path of the index:");
    string path = in.nextline().trim();
    while(path.length()==0){
      system.out.println("enter path of the index:");
      path = in.nextline().trim();
    }

    system.out.println("enter max hit number:");
    int max = in.nextint();
    while(max<0){
      system.out.println("enter max hit number:");
      max = in.nextint();
    }
    in.nextline();
    system.out.print("search>>> ");
    string text = in.nextline().trim();
    /*循环读入用户的关键词,如果是q则退出,长度为0也退出*/
    while(!text.equals("q")){
      if(text.length()>0){
        searchindex search = new searchindex(path);
        int hits = search.search("text", text, max);
        if(hits!=-1){
          search.printhits();
        }
      }
      system.out.print("search>>> ");
      text = in.nextline().trim();
    }
  }
}

ui界面(这里为了方便只是命令行的形式,可以根据需求写一个gui界面)

package webcrawler.ui;

import java.util.scanner;

import webcrawler.index.searchindex;

/**
 * @author lannooo
 *
 */
public class ui {
  public static void main(string[] args) {
    /*输入关键词*/
    scanner in = new scanner(system.in);
    system.out.print("search>>> ");
    string text = in.nextline().trim();
    /*对于用户的关键词,如果是q则退出,长度为0也退出*/
    while(!text.equals("q") && text.length()>0){
      searchindex search = new searchindex("d:/index-spider2");
      int hits = search.search("text", text, 20);
      if(hits!=-1){
        search.printhits();
      }
      system.out.print("search>>> ");
      text = in.nextline().trim();
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网