1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        用 Java 寫了一個(gè)搜索引擎系統(tǒng),這個(gè)太強(qiáng)了!!

        共 7838字,需瀏覽 16分鐘

         ·

        2022-05-15 16:17

        來源:https://blog.csdn.net/m0_57315623

        前言

        咱們?nèi)绻梦覀兊男》?wù)器去搞百度,搜狗那種引擎肯定是不行的,內(nèi)屬于全站搜索,我們這里做一個(gè)站內(nèi)搜索。這個(gè)還是可以的,就類似于我們對網(wǎng)站里的資源進(jìn)行搜索。

        一.搜索引擎怎么搜索

        搜索引擎就像一個(gè)小蜜蜂每天不停的采摘蜂蜜,就是去爬蟲各個(gè)網(wǎng)頁,然后通過爬取之后建立索引,以供于我們?nèi)ニ阉鳌?/span>

        這里我們可以使用Python,或者下載文檔壓縮包。這里我們下包把,快多了。本來想搞一個(gè)英雄聯(lián)盟的,實(shí)在找不見,要是后續(xù)有老鐵找到可以分享一下。

        建議大家別爬蟲(要不然被告了,不過我們學(xué)校的官網(wǎng)倒是可以隨便爬,我們當(dāng)時(shí)就是拿這個(gè)練手的) 為什么要用索引呢?

        因?yàn)榕赖臄?shù)據(jù)太多了,不索引,難道我去遍歷嗎?時(shí)間復(fù)雜度太大了。

        這里我們需要建立索引,索引分別為正排索引,和倒排索引。

        拿LOL舉個(gè)例子吧,正排就相當(dāng)于,我們提到無極劍圣的技能就可以聯(lián)想到:

        所以這是根據(jù)名字選技能

        倒排索引就是LOL里面誰有劍:

        1. 蠻王
        2. 無極劍圣
        3. 劍姬

        所以這是根據(jù)特點(diǎn)選擇英雄

        二.模塊劃分

        1.索引模塊

        1)掃描下載到的文檔,分析內(nèi)容,構(gòu)建出,正排索引和倒排索引。并且把索引內(nèi)容保存到文件中。

        2)加載制作i好的索引。并提供一些API實(shí)現(xiàn)查正排和查倒排這樣的功能。

        2.搜索模塊

        1)調(diào)用索引模塊,實(shí)現(xiàn)一個(gè)搜索的完整過程。

        輸入:用戶的查詢詞 輸出:完整的搜索結(jié)果

        3.web模塊

        需要實(shí)現(xiàn)一個(gè)簡單的web程序,能夠通過網(wǎng)頁的形式和用戶進(jìn)行交互。包含了前端和后端。

        三. 怎么實(shí)現(xiàn)分詞

        分詞的原理:

        1.基于詞庫

        嘗試把所有的詞都進(jìn)行窮舉,把這些結(jié)果放到詞典文件中。

        2.基于統(tǒng)計(jì)

        收集到很多的語料庫,進(jìn)行人工標(biāo)注,知道了那些字在一起的概率比較大~

        java中能夠?qū)崿F(xiàn)分詞的第三方工具也是有很多的

        比如ansj(聽說唱的兄弟可能聽過ansj,哈哈)這個(gè)就是一個(gè)maven中央倉庫的分詞第三方庫。最新面試題整理好了,點(diǎn)擊Java面試庫小程序在線刷題。

        我們直接下載最新版本然后放入pom.xml里面

        test包里直接操作:我們使用這個(gè)測試代碼直接搞。試一下這個(gè)包咋用。

        import?org.ansj.domain.Term;
        import?org.ansj.splitWord.analysis.ToAnalysis;
        import?java.util.List;
        public?class?TastAnsj?{
        ????public?static?void?main(String[]?args)?{
        ????????String?str?=?"易大師是一個(gè)有超高機(jī)動(dòng)性的刺客、戰(zhàn)士型英雄,擅長利用快速的打擊迅速擊潰對手,易大師一般打野和走單人路,作為無極劍道的最后傳人,易可以迅速砍出大量傷害,同時(shí)還能利用技能躲避猛烈的攻擊,避開敵人的集火。";
        ????????List?terms?=?ToAnalysis.parse(str).getTerms();
        ????????for?(Term?term?:?terms)?{
        ????????????System.out.println(term.getName());
        ????????}
        ????}
        }

        四.文件讀取

        把剛剛下載好的文檔的路徑復(fù)制到String中并且用常量標(biāo)記。

        這一步是為了用遍歷的方法把所有html文件搞出來,我們這里用了一個(gè)遞歸,如果是絕對路徑,就填加到文件鏈表,如果不是就遞歸,繼續(xù)添加里面的值。

        import?java.io.File;
        import?java.util.ArrayList;

        //讀取剛剛文檔
        public?class?Parser?{
        ?????private?static?final??String?INPUT_PATH="D:/test/docs/api";
        ??????public??void?run(){
        ??????????//整個(gè)Parser類的入口
        ??????????//1.根據(jù)路徑,去枚舉出所有的文件.(html);
        ??????????ArrayList?fileList=new?ArrayList<>();
        ??????????enumFile(INPUT_PATH,fileList);
        ??????????System.out.println(fileList);
        ??????????System.out.println(fileList.size());
        ??????????//2.針對上面羅列出的文件,打開文件,讀取文件內(nèi)容,并進(jìn)行解析
        ??????????//3.把在內(nèi)存中構(gòu)造好的索引數(shù)據(jù)結(jié)構(gòu),保定到指定的文件中。
        ??????}
        ??????//第一個(gè)參數(shù)表示從哪里開始遍歷?//第二個(gè)表示結(jié)果。
        ??????private?void?enumFile(String?inputPath,ArrayListfileList){
        ?????????File?rootPath=new?File(inputPath);
        ?????????//listFiles?能夠獲取到一層目錄下的文件
        ????????File[]?files=?rootPath.listFiles();
        ?????????for(File?f:files){
        ?????????????//根據(jù)當(dāng)前f的類型判斷是否遞歸。
        ?????????????//如果f是一個(gè)普通文件,就把f加入到fileList里面
        ?????????????//如果不是就調(diào)用遞歸
        ?????????????if(f.isDirectory()){
        ?????????????????enumFile(f.getAbsolutePath(),fileList);
        ?????????????}else?{
        ?????????????????fileList.add(f);
        ?????????????}
        ?????????}
        ??????}
        ????public?static?void?main(String[]?args)?{
        ????????//通過main方法來實(shí)現(xiàn)整個(gè)制作索引的過程
        ????????Parser?parser=new?Parser();
        ????????parser.run();
        ????}
        }

        我們嘗試運(yùn)行一下,這里的文件也太多了吧,而且無論是什么都打印出來了。所以我們下一步就是把這些文件進(jìn)行篩選,選擇有用的。最新面試題整理好了,點(diǎn)擊Java面試庫小程序在線刷題。

        else?{
        ?????????????????if(f.getAbsolutePath().endsWith(",html"))
        ?????????????????fileList.add(f);
        ?????????????}

        這個(gè)代碼就是只是針對末尾為html的文件。下圖就是展示結(jié)果。

        4.1 打開文件,解析內(nèi)容。

        這里分為三個(gè)分別是解析Title,解析Url,解析內(nèi)容Content。關(guān)注Java核心技術(shù),推送更多 Java 干貨!

        4.1.1解析Title

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(58, 58, 58);" data-linktype="2">f.getName()是直接讀取文件名字的方法。

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">我們用的name.substring(0,f.getName().length()-5);為什么要用總的文件名字長度減去5呢,因?yàn)?HTML剛好就是五。

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">private??String?parseTitle(File?f)?{
        ??????????String?name=?f.getName();
        ?????????return?name.substring(0,f.getName().length()-5);

        ????}

        4.1.2解析Url操作

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">這里的url就是我們平時(shí)去一個(gè)瀏覽器輸入一個(gè)東西下面會(huì)有一個(gè)url,這個(gè)url就是我們的絕對路徑經(jīng)過截取獲得出我們的相對的目錄,然后與我們的http進(jìn)行拼接,這樣就可以直接得到一個(gè)頁面。

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">private??String?parseUrl(File?f)?{
        ??????String?part1="https://docs.oracle.com/javase/8/docs/api/";
        ??????String?part2=f.getAbsolutePath().substring(INPUT_PATH.length());
        ??????????return?part1+part2;
        ????}

        4.1.3解析內(nèi)容

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">以<>為開關(guān)進(jìn)行對數(shù)據(jù)的讀取,以int類型讀取,為什么要用int而不是char呢因?yàn)閕nt類型讀完之后就變成-1可以判斷一下是否讀取完畢。具體代碼如下很容易理解。

        '){????????????????????????????isCopy=true;????????????????????????}????????????????????}????????????}????????????return??content.toString();????????}?catch?(FileNotFoundException?e)?{????????????e.printStackTrace();????????}????????return?'';????}這一模塊總的代碼塊如下:" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">private??String?parseContent(File?f)?throws?IOException?{
        ??????????//先按照一個(gè)一個(gè)字符來讀取,以<>作為開關(guān)
        ????????try(FileReader?fileReader=new?FileReader(f))?{
        ????????????//加上一個(gè)是否拷貝的開關(guān).
        ????????????boolean?isCopy=true;
        ????????????//還需要準(zhǔn)備一個(gè)結(jié)果保存
        ????????????StringBuilder?content=new?StringBuilder();
        ????????????while?(true){
        ????????????????//此處的read的返回值是int,不是char
        ????????????????//如果讀到文件末尾,就會(huì)返回-1,這是用int的好處;
        ????????????????int??ret?=?0;
        ????????????????try?{
        ????????????????????ret?=?fileReader.read();
        ????????????????}?catch?(IOException?e)?{
        ????????????????????e.printStackTrace();
        ????????????????}
        ????????????????if(ret==-1)?{
        ????????????????????????break;
        ????????????????????}
        ????????????????????char?c=(char)?ret;
        ????????????????????if(isCopy){
        ????????????????????????if(c=='<'){
        ????????????????????????????isCopy=false;
        ????????????????????????????continue;
        ????????????????????????}
        ????????????????????????//其他字符直接拷貝
        ????????????????????????if(c=='\n'||c=='\r'){
        ????????????????????????????c='?';
        ????????????????????????}
        ????????????????????????content.append(c);
        ????????????????????}else{
        ????????????????????????if(c=='>'){
        ????????????????????????????isCopy=true;
        ????????????????????????}
        ????????????????????}
        ????????????}

        ????????????return??content.toString();
        ????????}?catch?(FileNotFoundException?e)?{
        ????????????e.printStackTrace();
        ????????}
        ????????return?"";
        ????}

        這一模塊總的代碼塊如下:

        import?java.io.File;
        import?java.io.FileNotFoundException;
        import?java.io.FileReader;
        import?java.io.IOException;
        import?java.util.ArrayList;

        //讀取剛剛文檔
        public?class?Parser?{
        ?????private?static?final??String?INPUT_PATH="D:/test/docs/api";
        ??????public??void?run(){
        ??????????//整個(gè)Parser類的入口
        ??????????//1.根據(jù)路徑,去枚舉出所有的文件.(html);
        ??????????ArrayList?fileList=new?ArrayList<>();
        ??????????enumFile(INPUT_PATH,fileList);
        ??????????System.out.println(fileList);
        ??????????System.out.println(fileList.size());
        ??????????//2.針對上面羅列出的文件,打開文件,讀取文件內(nèi)容,并進(jìn)行解析
        ??????????for?(File?f:fileList){
        ??????????????System.out.println("開始解析"+f.getAbsolutePath());
        ??????????????parseHTML(f);
        ??????????}
        ??????????//3.把在內(nèi)存中構(gòu)造好的索引數(shù)據(jù)結(jié)構(gòu),保定到指定的文件中。
        ??????}

        ????private??String?parseTitle(File?f)?{
        ??????????String?name=?f.getName();
        ?????????return?name.substring(0,f.getName().length()-5);

        ????}
        ????private??String?parseUrl(File?f)?{
        ??????String?part1="https://docs.oracle.com/javase/8/docs/api/";
        ?????????String?part2=f.getAbsolutePath().substring(INPUT_PATH.length());
        ??????????return?part1+part2;
        ????}
        ????private??String?parseContent(File?f)?throws?IOException?{
        ??????????//先按照一個(gè)一個(gè)字符來讀取,以<>作為開關(guān)
        ????????try(FileReader?fileReader=new?FileReader(f))?{
        ????????????//加上一個(gè)是否拷貝的開關(guān).
        ????????????boolean?isCopy=true;
        ????????????//還需要準(zhǔn)備一個(gè)結(jié)果保存
        ????????????StringBuilder?content=new?StringBuilder();
        ????????????while?(true){
        ????????????????//此處的read的返回值是int,不是char
        ????????????????//如果讀到文件末尾,就會(huì)返回-1,這是用int的好處;
        ????????????????int??ret?=?0;
        ????????????????try?{
        ????????????????????ret?=?fileReader.read();
        ????????????????}?catch?(IOException?e)?{
        ????????????????????e.printStackTrace();
        ????????????????}
        ????????????????if(ret==-1)?{
        ????????????????????????break;
        ????????????????????}
        ????????????????????char?c=(char)?ret;
        ????????????????????if(isCopy){
        ????????????????????????if(c=='<'){
        ????????????????????????????isCopy=false;
        ????????????????????????????continue;
        ????????????????????????}
        ????????????????????????//其他字符直接拷貝
        ????????????????????????if(c=='\n'||c=='\r'){
        ????????????????????????????c='?';
        ????????????????????????}
        ????????????????????????content.append(c);
        ????????????????????}else{
        ????????????????????????if(c=='>'){
        ????????????????????????????isCopy=true;
        ????????????????????????}
        ????????????????????}
        ????????????}

        ????????????return??content.toString();
        ????????}?catch?(FileNotFoundException?e)?{
        ????????????e.printStackTrace();
        ????????}
        ????????return?"";
        ????}
        ????private?void?parseHTML?(File?f){
        ????????//解析出標(biāo)題
        ??????????String?title=parseTitle(f);
        ????????//解析出對應(yīng)的url
        ??????????String?url=parseUrl(f);
        ????????//解析出對應(yīng)的正文
        ????????try?{
        ????????????String?content=parseContent(f);
        ????????}?catch?(IOException?e)?{
        ????????????e.printStackTrace();
        ????????}
        ????}
        ??????//第一個(gè)參數(shù)表示從哪里開始遍歷?//第二個(gè)表示結(jié)果。
        ??????private?void?enumFile(String?inputPath,ArrayListfileList){
        ?????????File?rootPath=new?File(inputPath);
        ?????????//listFiles?能夠獲取到一層目錄下的文件
        ????????File[]?files=?rootPath.listFiles();
        ?????????for(File?f:files){
        ?????????????//根據(jù)當(dāng)前f的類型判斷是否遞歸。
        ?????????????//如果f是一個(gè)普通文件,就把f加入到fileList里面
        ?????????????//如果不是就調(diào)用遞歸
        ?????????????if(f.isDirectory()){
        ?????????????????enumFile(f.getAbsolutePath(),fileList);
        ?????????????}else?{
        ?????????????????if(f.getAbsolutePath().endsWith(".html"))
        ?????????????????fileList.add(f);
        ?????????????}
        ?????????}
        ??????}
        ????public?static?void?main(String[]?args)?{
        ????????//通過main方法來實(shí)現(xiàn)整個(gè)制作索引的過程
        ????????Parser?parser=new?Parser();
        ????????parser.run();
        ????}
        }


        END


        推薦閱讀

        一鍵生成Springboot & Vue項(xiàng)目!【畢設(shè)神器】

        Java可視化編程工具系列(一)

        Java可視化編程工具系列(二)


        順便給大家推薦一個(gè)GitHub項(xiàng)目,這個(gè) GitHub 整理了上千本常用技術(shù)PDF,絕大部分核心的技術(shù)書籍都可以在這里找到,

        GitHub地址:https://github.com/javadevbooks/books

        電子書已經(jīng)更新好了,你們需要的可以自行下載了,記得點(diǎn)一個(gè)star,持續(xù)更新中..



        瀏覽 59
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            高清无码内射视频 | 老女人的逼| 男生插女生b | 久久国产精品精品国产色综合 | 久久夜夜 | 大香蕉视频性生活网站 | 抽插久久 | 懂色Av懂色Aⅴ精彩AV | 成人网站在线免费 | 国产女人爽到高潮免费视频 |