搜索引擎项目

本文档介绍了搜索引擎项目,包括主页的搜索框、搜索结果页的构成,以及搜索引擎工作原理。项目核心是倒排索引,用于提高搜索效率。项目分为预处理、索引、搜索和前端展示模块,实现了对Java API文档的高效搜索。
摘要由CSDN通过智能技术生成

什么是搜索引擎?

1.有一个主页,有搜索框,在搜索框中输入的内容称为“查询词”。

例如:百度搜索
在这里插入图片描述

2.还有搜索结果页,包含若干条搜索结果。

在这里插入图片描述

3.针对每一个搜索结果,都会包含查询词或者查询词的一部分和查询词具有一定的相关性。

例如:上图中标红的词。

4.每个搜索结果包含好几个部分:

4.1标题

4.2描述—通常是页面的摘要信息

4.3子链接

4.4展示url

4.5图片

4.6点击url----点击url将会跳转到目标url上

搜索引擎的功能

查找用户输入的查询词在哪些页面中出现过或者出现过一部分,把结果展示到页面上,点击结果就能跳转到该页面。
自然搜索结果:网页的数据通常是通过爬虫来获取的。
广告搜索结果:广告代理商把内容提交给平台。

像百度,搜狗这样的搜索引擎,是全网搜索,处理的数据量是非常巨大。

当前项目是搜索Java官方API文档。

为什么做Java API文档搜索?

1.官方文档上没有一个好用的搜索框。
2.JavaAPI文档数量比较少,设备资源有限。
3.文档内容不需要使用爬虫来获取,可以直接在官网上下载。

搜索引擎是如何工作的?

搜索引擎需要在很多的网页数据中找到用户输入的查询词(部分查询词)。
搜索引擎后台已经获取了很多很多的网页数据,每个网页数据都是一个html。称为一个“文档”。搜索引擎要知道该查询词在哪些文档出现过。

1.暴力搜索

依次遍历每个文件,查看当前文件中是否包含查询词。(文档数据多,效率低下)

2.倒排索引(这是一种特殊的数据结构)

要理解倒排索引,我们先要了解正排索引。首先我们要进行分词,然后对每个词的出现进行统计。
正排索引就是:现有文档,每个文档都有一个ID,然后文档中的内容进行分词,统计每个词出现的次数。通过文档->词建立关系,这个就是正排索引。
例如:
假设我们搜一个关键字(Tom),当100个网页的10个网页含有Tom这个关键字。但是由于是正排是文档id作为索引的,所以我们不得不把100个网页都扫描一遍,然后找出其中含有Tom的10个网页。然后再进行rank,sort等。效率就比较低了。
正排索引易维护,但是查找效率慢。

倒排索引就是通过词->文档建立关系,建立的是出现这个词的所有文档。
例如:
假设我们搜一个关键字(Tom),当100个网页的10个网页含有Tom这个关键字。由于是倒排是词作为索引的,所以我们只需把10个网页扫描一遍,再进行rank,sort等。效率就比较高了。
倒排索引查找效率高,但是维护教难。

倒排索引是项目最核心的部分,也是搜索引擎中最核心的部分

对用户的查询词进行分词

使用现成的第三方库进行分词

我们先下载好官方API文档,分析里面的内容,在搜索结果中填上线上文档的链接地址

项目模块划分:

1.预处理模块:把下载好的html文档进行一次初步的处理(简单分析结构并且处理掉其中的html标签)
2.索引模块:预处理得到的结果,构建正排索引+倒排索引
3.搜索模块:完成一次搜索过程基本流程(从用户输入查询词,到得到最终的搜索结果)。
4.前端模块:有一个页面,展示结果并且让用户输入数据

预处理模块

把api目录中所有的html文件进行处理->得到一个单个文件。使用行文本的方式进行组织。
这个得到的临时文件中,每一行对应到一个html文档,每一行中又包含3列。第一列表示这个文档的标题,第二列表示这个文档的url,第三列表示这个文档的正文(去掉html标签).

去除html是一个字符一个字符的读取,如果字符为‘<’,我们将标志位置位false,如果是‘>’我们将标志位置位true,如果标志位为true,我们才进行写入到StringBuilder中

去掉之后将得到的结果输入到文件中。

package parser;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

//遍历文档目录,读取所有的 html 文档内容,把结果解析成行文本文件
//每一行都对应一个文档,每一行都包含文档标题,文档的url,文档的正文
//Parser 是一个单独的可执行类
public class Parser {
   
    //输入目录表示下载好的 JavaAPI文档
    private static final String INPUT_PATH = "";
    //输出目录表示预处理模块输出文件存放的目录
    private static final String OUTPUT_PATH = "";

    public static void main(String[] args) throws IOException {
   
        FileWriter resultFileWriter = new FileWriter(new File(OUTPUT_PATH));
        //通过main完成整个预处理的过程
        //1.枚举出 INPUT_PATH 中所有的 html 文件(递归)
        ArrayList<File> fileList = new ArrayList<>();
        enumFile(INPUT_PATH, fileList);
        //2.针对枚举出来的 html 文件路径进行遍历,依次打开每个文件,并读取内容
        //  把内容转换成需要的结构化的数据(DocInfo对象)
        for (File f : fileList) {
   
            System.out.println("converting " + f.getAbsolutePath() + "...");
            //最终输出的是 raw_data 文件是一个行文本文件.每一行对应一个 html 文件
            //line 这个对象就对应到一个文件
            String line = convertLine(f);
            //3.把得到的结果写入到最终的输出文件中(OUTPUT_PATH),写成行文本的形式
            resultFileWriter.write(line);
        }
        resultFileWriter.close();
    }

    private static String convertLine(File f) throws IOException {
   
        //1.根据f 转换出标题
        String title = convertTitle(f);
        //2.根据f 转换出url
        String url = convertUrl(f);
        //3.根据f 转换出正文
        String content = convertContent(f);
        //4.把这三个部分拼成一行文本
        //  \3是分割3个部分的作用 \3是不可见的
        return title + "\3" + url + "\3" + content + "\n";
    }

    private static String convertContent(File f) throws IOException {
   
        //这个方法做两件事情:
        //1.把html中的标签去掉
        //2.把 \n 去掉
        //一个一个字符读取并判定
        FileReader fileReader = new FileReader(f);
        boolean isContent = true;
        StringBuilder output = new StringBuilder();
        while (true) {
   
            int ret = fileReader.read();
            if (ret == -1) {
   
                //读取完毕
                break;
            }
            char c = (char) ret;
            if (isContent) {
   
                //当前这部分是正文
                if (c == '<') {
   
                    isContent = false;
                    continue;
                }
                if (c == '\n' || c == '\r') {
   
                    c = ' ';
                }
                output.append(c);
            } else {
   
                //当前是标签
                //不去写 output
                if (c == '>') {
   
                    isContent = true;
                }
            }
        }
        fileReader.close();
        return output.toString();
    }

    private static String convertUrl(File f) {
   
        //url由两部分组成
        //第一部分https://docs.oracle.com/javase/8/docs/api
        //第二部分 /java/util/Collection.html
        String part1 = "https://docs.oracle.com/javase/8/docs/api";
        String part2 = f.getAbsolutePath().substring(INPUT_PATH.length());
        return part1 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值