当前位置: 首页 > 后端技术 > Java

我用Java写了一个搜索引擎系统,太强大了,..

时间:2023-04-01 15:51:39 Java

来源:https://blog.csdn.net/m0_5731...前言如果用我们的小服务器去搞百度,搜狗这样的引擎肯定不行,内搜是全站的,所以我们将在这里做一个站点搜索。这个还是可以的,类似于我们在网站上搜索资源。1.搜索引擎如何搜索?搜索引擎就像一只蜜蜂,每天都在不停地采蜜。它爬取各种网页,然后爬取之后建立索引供我们搜索。这里我们可以使用Python,或者下载文档zip包。让我们在这里解压,它更快。本来想开个英雄联盟,没找到。如果有人以后找到它,我可以分享它。建议大家不要爬(不然会被骂的,不过我们学校的官网可以随便爬,我们当时就是用这个来练习的)为什么要用索引呢?因为爬取的数据太多,又没有索引,要不要遍历?时间复杂度太大。这里我们需要创建一个索引,索引有正向索引和倒排索引。我们以LOL为例。前排是等价的。提起无极剑圣的技能,我们可以想到:Q技能阿尔法突袭W技能冥想E技能无双R技能高原血所以这是一个根据名字选出的技能的倒排索引在LOL中谁有剑:蛮王无极剑圣剑仙所以这里是按特性选英雄2.模块划分1.索引模块1)扫描下载的文档,分析内容,构建正向索引和倒排索引。并将索引内容保存到文件中。2)加载索引i。并提供一些API来实现前向后向检查等功能。2、搜索模块1)调用索引模块,实现一个完整的搜索过程。输入:用户的查询输出:完整的搜索结果3.web模块需要实现一个简单的web程序,可以以网页的形式与用户进行交互。包含前端和后端。3、如何实现分词原理:1、尝试穷举所有基于词库的词,并将这些结果放入字典文件中。2.根据统计收集了很多语料,手动标注,就知道那些词在一起的概率比较高~java中也有很多第三方工具可以实现分词,比如ansj(谁的兄弟听说过singing可能听说过ansj,哈哈)这是maven中央仓库的一个分词第三方库。我们直接下载最新版本放到pom.xml中的测试包中直接运行:我们直接用这个测试代码来做。试试如何使用这个包。importorg.ansj.domain.Term;importorg.ansj.splitWord.analysis.ToAnalysis;importjava.util.List;publicclassTastAnsj{publicstaticvoidmain(String[]args){Stringstr="易大师是一个超高机动性的刺客、战士类英雄,擅长以快速的一击快速击败对手。易大师一般都是打野单走,使用技能躲避猛烈攻击,躲避敌人火力。";Listterms=ToAnalysis.parse(str).getTerms();for(Termterm:terms){System.out.println(term.getName());}}}4.文件读取将刚刚下载的文档的路径复制到String中,并用常量标记。这一步是用遍历的方法把html文件全部取出来。我们在这里使用递归。如果是绝对路径,则会添加到文件列表中。如果不是,就会递归,继续把里面的值相加。importjava.io.File;importjava.util.ArrayList;//读取刚才的文档publicclassParser{privatestaticfinalStringINPUT_PATH="D:/test/docs/api";publicvoidrun(){//整个Parser类的入口//1.根据路径,枚举所有文件。(html);ArrayList<文件>fileList=newArrayList<>();枚举文件(输入路径,文件列表);System.out.println(文件列表);System.out.println(fileList.size());//2。对于上面列出的文件,打开文件,读取文件内容,进行分析//3.把在内存中构建的索引数据结构保存到指定的文件中。}//第一个参数表示从哪里开始遍历//第二个表示结果。privatevoidenumFile(StringinputPath,ArrayListfileList){FilerootPath=newFile(inputPath);//listFiles可以得到一个目录下的文件File[]files=rootPath.listFiles();for(Filef:files){//根据f的当前类型判断是否递归。//如果f是普通文件,将f加入fileList//如果不是,递归调用if(f.isDirectory()){enumFile(f.getAbsolutePath(),fileList);}else{fileList.add(f);}}}publicstaticvoidmain(String[]args){//使用main方法实现索引Parser的全过程parser=newParser();解析器.run();}}试运行一下,这里文件太多了,打印出来了。所以我们的下一步是过滤这些文件并选择有用的文件。else{if(f.getAbsolutePath().endsWith(",html"))fileList.add(f);}此代码仅适用于末尾带有html的文件。下图显示了结果。4.1打开文件并解析内容。分为解析Title、解析Url、解析内容三部分。4.1.1解析Titlef.getName()是直接读取文件名的方法。我们使用了name.substring(0,f.getName().length()-5);为什么我们要从文件名总长度中减去5,因为.HTML就是5。privateStringparseTitle(Filef){Stringname=f.getName();返回name.substring(0,f.getName().length()-5);}4.1.2解析Url操作这里的url就是我们常用的去浏览器输入一些东西,下面就会有一个url。这个url就是我们的绝对路径,截取得到我们的相对目录,然后和我们的http拼接,这样就可以直接得到一个页面。privateStringparseUrl(Filef){Stringpart1="https://docs.oracle.com/javase/8/docs/api/";字符串part2=f.getAbsolutePath().substring(INPUT_PATH.length());返回第1部分+第2部分;}4.1.3解析内容使用<>作为读取数据的开关,以int类型读取。为什么使用int而不是char?因为int类型读取后变成了-1所以可以判断Check看是否读取过了。具体代码如下,简单易懂。privateStringparseContent(Filef)throwsIOException{//先一个一个读取字符,以<>为开关try(FileReaderfileReader=newFileReader(f)){//加一个开关是否复制。布尔isCopy=true;//还需要准备一个结果保存StringBuildercontent=newStringBuilder();while(true){//这里read的返回值是int,不是char//如果读到文件末尾,会返回-1,这是使用int的好处;intret=0;尝试{ret=fileReader.read();}catch(IOExceptione){e.printStackTrace();}if(ret==-1){中断;}charc=(char)ret;if(isCopy){if(c=='<'){isCopy=false;继续;}//直接复制其他字符if(c=='\n'||c=='\r'){c='';}content.append(c);}else{if(c=='>'){isCopy=true;}}}返回content.toString();}catch(FileNotFoundExceptione){e.printStackTrace();}返回””;}该模块的通用代码块如下:importjava.io.File;importjava.io.FileNotFoundException;importjava.io.FileReader;importjava.io.IOException;importjava.util.ArrayList;//Read刚才的文档publicclassParser{privatestaticfinalStringINPUT_PATH="D:/test/docs/api";publicvoidrun(){//整个Parser类的入口//1.根据路径,枚举所有文件。(html);ArrayList<文件>fileList=newArrayList<>();枚举文件(输入路径,文件列表);System.out.println(文件列表);System.out.println(fileList.size());//2。对于以上列出列出的文件,打开文件,读取文件内容,解析为(Filef:fileList){System.out.println("开始解析"+f.getAbsolutePath());解析HTML(f);}//3。将在内存中构建的索引数据结构保存到指定文件中}privateStringparseTitle(Filef){Stringname=f.getName();返回name.substring(0,f.getName().length()-5);}privateStringparseUrl(Filef){Stringpart1="https://docs.oracle.com/javase/8/docs/api/";字符串part2=f.getAbsolutePath().substring(INPUT_PATH.length());返回第1部分+第2部分;}privateStringparseContent(Filef)throwsIOException{//首先一个一个读取字符,使用<>作为开关try(FileReaderfileReader=newFileReader(f)){//添加一个开关是否复制。布尔isCopy=true;//还需要准备一个结果保存StringBuildercontent=newStringBuilder();while(true){//这里read的返回值是int,不是char//如果读到文件末尾,会返回-1,用int的好处;intret=0;尝试{ret=fileReader.read();}catch(IOExceptione){e.printStackTrace();}如果(ret==-1){中断;}charc=(char)ret;if(isCopy){if(c=='<'){isCopy=false;继续;}//其他字符直接复制if(c=='\n'||c=='\r'){c='';}content.append(c);}else{if(c=='>'){isCopy=true;}}}返回content.toString();}catch(FileNotFoundExceptione){e.printStackTrace();}返回””;}privatevoidparseHTML(Filef){//解析出标题Stringtitle=parseTitle(f);//解析对应的urlStringurl=parseUrl(f);//解析对应的文本try{字符串内容=parseContent(f);}catch(IOExceptione){e.printStackTrace();}}//第一个参数表示从哪里开始遍历//第二个表示结果privatevoidenumFile(StringinputPath,ArrayListfileList){FilerootPath=newFile(inputPath);//listFiles可以得到一个目录下的文件File[]files=rootPath.listFiles();for(Filef:files){//根据当前f的类型判断是否递归。//如果f是普通文件,将f加入fileList//如果不是,递归调用if(f.isDirectory()){enumFile(f.getAbsolutePath(),fileList);}else{if(f.getAbsolutePath().endsWith(".html"))fileList.add(f);}}}publicstaticvoidmain(String[]args){//使用main方法实现整个索引制作过程Parserparser=newParser();解析器.run();}}近期热点文章推荐:1.1000+Java面试题及答案(2022最新版)2.厉害了!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!