国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

站內(nèi)搜索引擎

這篇具有很好參考價值的文章主要介紹了站內(nèi)搜索引擎。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1.什么是搜索引擎?

如圖所示:

站內(nèi)搜索引擎

我用的是谷歌瀏覽器,但是我的搜索引擎可以跟換 。切換到bing主頁站內(nèi)搜索引擎

在搜索框中我們輸入一段話,跳到一個帶有搜索結(jié)果的頁面如下:

站內(nèi)搜索引擎

站內(nèi)搜索引擎

搜索引擎的核心功能:查找用戶輸入的詞/一句話 相關(guān)聯(lián)的網(wǎng)頁。?

搜索結(jié)果頁一條記錄包含的信息如下:

站內(nèi)搜索引擎

?當我們點擊標題,會跳轉(zhuǎn)到落地頁,如下圖:

站內(nèi)搜索引擎

相信大家對搜索引擎都有一定的了解了。

2.實現(xiàn)搜索引擎的核心思路:

  • 首先我需要很多網(wǎng)頁。
  • 再根據(jù)用戶輸入的詞/一句話,在這些網(wǎng)頁中進行查找。

搜索引擎的網(wǎng)頁又該如何獲取呢?

像百度,搜狗,這樣的大型搜索引擎,每天會有很多爬蟲去爬取大量網(wǎng)頁,在存儲起來。

我們這里先直接去官網(wǎng)下載jdk文檔(之后抽取時間改進利用爬蟲獲取網(wǎng)頁)。

用戶輸入查詢詞之后,如何去讓查詢詞語和當前的這些網(wǎng)頁進行匹配呢?

搜索引擎工作原理

利用這些網(wǎng)頁(.html文件解析過后,生成的文檔DocInfo)構(gòu)建正排索引和倒排索引。

3.正排索引和倒排索引原理:

正排,倒排原理理解

1.正排索引:文檔 id? ? ? ? ->? ? ? ? 文檔內(nèi)容? ? ? ? ? ? ? ? ????????(1個id對應(yīng)1個文檔內(nèi)容)

2.倒排索引:詞? ? ? ? ? ? ? ? ->? ? ? ? 和詞相關(guān)聯(lián)的文檔id? ? ? ? (1個詞對應(yīng)一個/多個文檔id)

舉個例子:

//正排索引

1? ? ? ? ? ? ? ? ? ? ? ? 我上街買了一份炸雞

2? ? ? ? ? ? ? ? ? ? ? ? 我晚飯吃了一份牛肉

//倒排索引(先分詞)

我? ? ? ? ? ? ? ? ? ? ? ? ????????1,2

上街? ? ? ? ? ? ? ? ? ? ? ? ? ? 1

買? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1

了? ? ? ? ? ? ? ? ? ? ? ? ????????1,2

一份? ? ? ? ? ? ? ? ? ? ????????1,2

炸雞? ? ? ? ? ? ? ? ? ? ? ? ????1?

晚飯? ? ? ? ? ? ? ? ? ? ? ??????2

吃? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2

牛肉? ? ? ? ? ? ? ? ? ? ? ? ????2

4.我要把搜索引擎做到什么程度?

?我們還是先做一個“站內(nèi)搜索”,類似于嗶哩嗶哩里的搜索框,搜索站內(nèi)的東西。我們要做一個java,jdk8文檔的搜索引擎,比如輸入一個ArrayList,會在頁面顯示一系列關(guān)于ArrayList文檔的信息,通過點擊標題或者utl跳轉(zhuǎn)到官網(wǎng)jdk8文檔。

5.獲取文檔(網(wǎng)頁)

Java Downloads | Oracle

站內(nèi)搜索引擎

先看看在線文檔的內(nèi)容以及url站內(nèi)搜索引擎

站內(nèi)搜索引擎

?https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html

?在對比看一下離線后的文檔路徑

站內(nèi)搜索引擎

?file:///C:/Users/Administrator/Desktop/online_search_doc/jdk-8u341-docs-all/docs/api/java/util/ArrayList.html

站內(nèi)搜索引擎

本地鏈接和在線網(wǎng)站鏈接相比得出結(jié)論:

我們可以基于離線文檔來制作索引,實現(xiàn)搜索?,當用戶在搜索結(jié)果頁面點擊具體的搜索結(jié)果的時候,就自動跳轉(zhuǎn)到在線文檔的頁面。

6.模塊粗略劃分:

1.索引模塊:

  • 掃描下載的文檔,分析文檔內(nèi)容,構(gòu)造出正排索引+倒排索引。并且把索引內(nèi)容保存到文件中
  • 加載制作好的索引,并提供一些API實現(xiàn)查正排和查倒排這樣的功能。

2.搜索模塊:

  • 調(diào)用索引模塊,實現(xiàn)一個搜索的完整過程
  • 輸入:用戶輸入詞/一句話
  • 輸出:完整的搜索結(jié)果(包含了很多條記錄,每個記錄都有標題,描述,展示url,并且點擊能夠跳轉(zhuǎn))

3.web模塊:

  • 需要實現(xiàn)一個簡單的web程序,能夠通過網(wǎng)頁的形式來和用戶交互~

7.創(chuàng)建項目

用到的工具:

idea專業(yè)版2022.2.1

webstorm專業(yè)版2022.2.1

8.介紹一下什么是分詞

用戶在使用時侯,往往會輸入一句話,比如:

站內(nèi)搜索引擎

會出現(xiàn)一下結(jié)果頁:

站內(nèi)搜索引擎

用戶輸入的話被分成好多個詞,每個詞又對應(yīng)很多文檔id,所以結(jié)果頁面會有很多條記錄,每條記錄都包括標題,url,描述這三個基本信息?。

我上街買了一份炸雞? ? ? ? 可分詞為:

上街

一份

炸雞

我們要使用第三方庫ansj來進行分詞。ansj地址

說一下分詞的原理,有助于編寫代碼。

1.基于詞庫(跟不上時代發(fā)展,每隔一段時間會出現(xiàn)新詞)

  • 嘗試把所有詞都進行窮舉~把這些窮舉結(jié)果放到詞典文件中。
  • 然后就可以依次的取句子中的內(nèi)容,每隔一個字,在詞典里查一下,每隔倆個字,查一下.....

2.基于統(tǒng)計(該方法更加科學,用的多)

  • 收集到很多很多的“語料庫” => "人工標注/直接統(tǒng)計? => "也就知道了哪些字放在一起的概率比較大~";
  • 分詞的實現(xiàn),就是屬于“人工智能”典型應(yīng)用場景~

分詞原理

寫個測試類用一下ansj這個第三方庫

站內(nèi)搜索引擎

說一下爆紅的原因:

在分詞的時候,會加載一些詞典文件,通過這些詞典文件能夠加快分詞速度和準確率,但是沒有這些詞典文件ansj仍然能快速分出詞。?(可配置詞典文件)

我們在來看一下分詞結(jié)果:

站內(nèi)搜索引擎

9.實現(xiàn)索引模塊Parser類的整體流程?

  • 指定本地jdk8文檔的路徑INPUT_PATH
  • Parser類作為入口,main函數(shù)調(diào)用run方法
  • run函數(shù)包含三個功能:
  • 1.根據(jù)指定路徑,羅列出該文件夾下所有的.html文件,包括子文件夾中的.html的路徑
  • 2.根據(jù)上邊羅列的所有html文件路徑,打開文件,讀取文件,解析文件,構(gòu)建索引(在內(nèi)存中)
  • 3.把在內(nèi)存中構(gòu)造好的索引數(shù)據(jù)結(jié)構(gòu),保存到指定的文件中(即序列化,反序列化)

10.遞歸枚舉文件

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

public class Parser {
    public static final String INPUT_PATH = "C:/Users/Administrator/Desktop/online_search_doc/jdk-8u341-docs-all/docs/api/";

    public void run() {
        //1.枚舉出所有的.html文件,包括子目錄中的文件
        ArrayList<File> filelist = new ArrayList<>();
        enumFile(INPUT_PATH, filelist);
//        System.out.println(filelist);
//        System.out.println(filelist.size());
        //2.針對上面羅列出的文檔路徑,打開文件,讀取文件內(nèi)容,進行解析,構(gòu)建索引
        //3.把在內(nèi)存中構(gòu)造好的索引數(shù)據(jù)結(jié)構(gòu),保存到指定的文件中
    }

    private void enumFile(String inputPath, ArrayList<File> filelist) {
        File rootPath = new File(inputPath);
        File[] files = rootPath.listFiles();
        for (File f : files) {
            if(f.isDirectory()){
                enumFile(f.getAbsolutePath(),filelist);
            }else {
                filelist.add(f);
            }
        }
    }

    public static void main(String[] args) {
        Parser parser = new Parser();
        parser.run();
    }
}

現(xiàn)在有一個問題,我要的是html文件,其他文件例如css,js等其他文件是我不想要它出現(xiàn)在結(jié)果里邊,用戶也看不懂,所以filelist里邊要去掉這些前端文件。

站內(nèi)搜索引擎

11.除去不是html的文件?

我怎么實現(xiàn)?

我的思路是得到所有文件的目錄,它的后綴不是html的就不加到那個filelist里邊

private void enumFile(String inputPath, ArrayList<File> filelist) {
        File rootPath = new File(inputPath);
        File[] files = rootPath.listFiles();
        for (File f : files) {
            if(f.isDirectory()){
                enumFile(f.getAbsolutePath(),filelist);
            }else {
                if(f.getAbsolutePath().endsWith(".html")){
                    filelist.add(f);
                }
            }
        }
    }

這里我想說的是,后續(xù)的開發(fā)中會遇到各種各樣的問題,但是只要思想不滑坡,辦法總比困難多。

浩大的工程,都是由一個一個小小的函數(shù)堆積起來的。好了,現(xiàn)在我們把所有的html文件都加載到filelist里邊了,現(xiàn)在的問題是,我怎么根據(jù)上邊的路徑打開文件去解析里邊的文件呢?解析,我要解析什么?(1.標題,2.url,3.描述(描述是根據(jù)正文來的,所以因該是解析正文)),我為什么要這三個東西?我要把這三個東西用一個弄一個實體類來表示,即一個DocInfo,里邊有id,title,url,content,然后通過一個ArrayList<DocInfo>構(gòu)建出一個正排索引,然后根據(jù)這個正排索引去構(gòu)建倒排索引,目前先考慮這么多。

12.解析html

站內(nèi)搜索引擎

站內(nèi)搜索引擎

我們打開文件發(fā)現(xiàn)html的名字和文件中的title里的名字相似,但是html的名字更加獲取,代碼實現(xiàn)上更加容易,我們就以html前邊的單詞作為標題 。

站內(nèi)搜索引擎

?站內(nèi)搜索引擎

這樣的話,我們解析html的標題的功能完成了。我們繼續(xù)往下做。

13.解析url

站內(nèi)搜索引擎

我們所期望的結(jié)果就是,用戶點擊搜索結(jié)果,就能夠跳轉(zhuǎn)到對應(yīng)的線上文檔的頁面。

思路:

把本地路徑的后半段提取出來作為后綴? ? ? ? ?java/util/ArrayList.html

以在線路徑前半部分為前綴? ? ? ? ? ? ?https://docs.oracle.com/javase/8/docs/api/

拼接后就是完整的url?????????https://docs.oracle.com/javase/8/ docs/api/java/util/ArrayList.html

寫一個測試代碼:

import java.io.File;

public class TestUrl {
    public static final String INPUT_PATH = "C:/Users/Administrator/Desktop/online_search_doc/jdk-8u341-docs-all/docs/api/";

    public static void main(String[] args) {
        File f = new File("C:/Users/Administrator/Desktop/online_search_doc/jdk-8u341-docs-all/docs/api/java/util/ArrayList.html");
        String part1 = "https://docs.oracle.com/javase/8/docs/api/";
        String part2 = f.getAbsolutePath().substring(INPUT_PATH.length());
        System.out.println(part1+part2);
    }
}

站內(nèi)搜索引擎

這里雖然是反斜杠,但是粘貼在瀏覽器上還能打開,體現(xiàn)出瀏覽器的魯棒性。

我們優(yōu)化一下吧,把\都替換成/.

具體方法:

站內(nèi)搜索引擎

注意:

站內(nèi)搜索引擎

?雖然沒看懂,但是能用!接下來我們開始解析正文,先講講解析正文的思路:

14.解析正文

我們先打開一個html文件觀察觀察

站內(nèi)搜索引擎

這里邊有script的代碼,還有css的代碼style,還有html的標簽

這里我們使用正則表達式去除一下這些標簽

具體代碼:

public String parseContent(File f) {
        try (FileReader fileReader = new FileReader(f)) {
            StringBuilder content = new StringBuilder();
            while (true) {
                int ret = fileReader.read();
                if (ret == -1) {
                    break;
                }
                char c = (char) ret;
                content.append(c);
            }
            String scriptRegex = "<script[^>]*?>[\\s\\S]*?<\\/script>";
            //定義style的正則表達式,去除style樣式,防止css代碼過多時只截取到css樣式代碼
            String styleRegex = "<style[^>]*?>[\\s\\S]*?<\\/style>";
            //定義HTML標簽的正則表達式,去除標簽,只提取文字內(nèi)容
            String htmlRegex = "<[^>]+>";
            //定義回車,換行符,制表符
            String spaceRegex = "\t|\r|\n";

            String content_final = content.toString();
            content_final = content_final.replaceAll(scriptRegex, "");
            content_final = content_final.replaceAll(styleRegex, "");
            content_final = content_final.replaceAll(htmlRegex, "");
            content_final = content_final.replaceAll(spaceRegex,"");

            return content_final;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

效果展示:

站內(nèi)搜索引擎

?嗯不錯不錯~(蜜汁自信)

現(xiàn)在的問題是,我們已經(jīng)把東西解析出來了,我們現(xiàn)在需要一個索引類去把解析出來的東西加入到索引,然后將制作好的索引保存到指定文件中去。

15.實現(xiàn)索引模塊

先創(chuàng)建一個Index類,這個類的主要實現(xiàn)方法:

//給定一個docId,在正排索引中,查詢文檔的詳細信息
//給定一個詞,在倒排索引中,查哪些文檔和這個詞相關(guān)聯(lián)
//往索引中新增一個文檔
//把內(nèi)存中的索引結(jié)構(gòu)保存到磁盤中
//把磁盤中的索引數(shù)據(jù)加載到內(nèi)存中

然后創(chuàng)建一個DocInfo類,這個實體類來描述docId,title,url,content.

站內(nèi)搜索引擎

這里有一個問題,返回值是List<Integer>行不行?用戶輸入一個詞/一句話,我返回了文章的id難道不對嗎?如過這樣做的話,就體現(xiàn)不出文章的相關(guān)性了,排在前邊的永遠是docId小的文章。為了解決這樣的問題,修改一下返回值。

創(chuàng)建一個類Weight,權(quán)重的意思,Weight里邊包含docId,和weight這倆個屬性,weight值越大,我們就表示,用戶輸入的值和文章的相關(guān)性越強,在瀏覽器顯示的越靠前。這個Weight類就是把文檔id和文檔與詞的相關(guān)性進行一個包裹。

站內(nèi)搜索引擎

具體實現(xiàn)代碼:

import java.util.List;

//通過這個類在內(nèi)存中構(gòu)造出索引
public class Index {
    //給定一個docId,在正排索引中,查詢文檔的詳細信息
    public DocInfo getDocInfo(int docId) {
        return null;
    }

    //給定一個詞,在倒排索引中,查哪些文檔和這個詞相關(guān)聯(lián)
    public List<Weight> getInverted(String term) {
        return null;
    }

    //往索引中新增一個文檔
    public void addDoc(String title, String url, String content) {

    }
    //把內(nèi)存中的索引結(jié)構(gòu)保存到磁盤中
    public void save(){

    }
    //把磁盤中的索引數(shù)據(jù)加載到內(nèi)存中
    public void load(){
        
    }
}

我們現(xiàn)在還需要倆個結(jié)構(gòu)表示正排索引和倒排索引:

現(xiàn)在在想一下,正排索引是通過一個docId返回一個DocInfo,而倒排索引可以通過一個詞返回一組docId,為了讓詞和docId有相關(guān)性,所以進行如下編碼:

private ArrayList<DocInfo> forwardIndex = new ArrayList<>();

private HashMap<String,ArrayList<Weight>> invertedIndex = new HashMap<>();

現(xiàn)在我有一個問題,查正排,和查倒排效率高嗎?時間復(fù)雜度是多少?

查正排,我們用的是ArrayList,時間復(fù)雜度是O(1)

查倒排,我們用的是HashMap,時間復(fù)雜度是O(1)

所以說,查詢的很快,我們用這樣的結(jié)構(gòu)來保證查詢的夠快,夠高效。

還有就是,我們現(xiàn)在的數(shù)據(jù)都是放在內(nèi)存上的,這是查詢快的第二個原因。

目前,實現(xiàn)的代碼如下:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

//通過這個類在內(nèi)存中構(gòu)造出索引
public class Index {
    private ArrayList<DocInfo> forwardIndex = new ArrayList<>();

    private HashMap<String,ArrayList<Weight>> invertedIndex = new HashMap<>();
    //給定一個docId,在正排索引中,查詢文檔的詳細信息
    public DocInfo getDocInfo(int docId) {
        return forwardIndex.get(docId);
    }

    //給定一個詞,在倒排索引中,查哪些文檔和這個詞相關(guān)聯(lián)
    public List<Weight> getInverted(String term) {
        return invertedIndex.get(term);
    }

    //往索引中新增一個文檔
    public void addDoc(String title, String url, String content) {
        //構(gòu)建正排索引
        DocInfo docInfo = buildForward(title,url,content);
        //構(gòu)建倒排索引
        buildInverted(docInfo);
    }

    private void buildInverted(DocInfo docInfo) {
        
    }

    private DocInfo buildForward(String title, String url, String content) {
        DocInfo docInfo = new DocInfo();
        docInfo.setDocId(forwardIndex.size());
        docInfo.setTitle(title);
        docInfo.setUrl(url);
        docInfo.setContent(content);
        forwardIndex.add(docInfo);
        return docInfo;
    }

    //把內(nèi)存中的索引結(jié)構(gòu)保存到磁盤中
    public void save(){

    }
    //把磁盤中的索引數(shù)據(jù)加載到內(nèi)存中
    public void load(){

    }
}

目前,我們新增文檔的功能還沒實現(xiàn)完,正排索引構(gòu)建好了,現(xiàn)在實現(xiàn)構(gòu)建倒排索引,怎么構(gòu)建?

怎么做?倒排索引就是詞與docId的映射,我準備,把傳入的docInfo,把它的title,和content進行分詞,我倒排索引用的是HashMap<String,ArrayList<Weight>>,也就是詞和權(quán)重的鍵值對。權(quán)重里邊包括docId,weight,我們又如何確定這個權(quán)重的值, (權(quán)重這個值,描述了詞個文檔之間的相關(guān)性,權(quán)重值越大,我們認為詞和文章id相關(guān)性越強,在網(wǎng)頁上顯示的也就越靠前)。

在真實的搜索引擎中,這里的相關(guān)性,是一個非常復(fù)雜的邏輯,往往是一個專門的算法團隊來進行負責的。根據(jù)文檔中提取的特征,訓練模型,最終借助機器學習的方式來衡量相關(guān)性。

現(xiàn)在我對構(gòu)建倒排索引做如下規(guī)劃:

1.針對文檔標題進行分詞

2.遍歷分詞結(jié)果,統(tǒng)計每個詞出現(xiàn)的次數(shù)

3.針對正文進行分詞

4.遍歷分詞結(jié)果,統(tǒng)計每個詞出現(xiàn)的次數(shù)

5.把上面的結(jié)果匯總到一個HashMap里面。

6.遍歷剛才這個HashMap,依次來更新倒排索引中的結(jié)構(gòu)。

現(xiàn)在,我們想一想,標題中出現(xiàn)的詞,和正文出現(xiàn)的詞相比,標題出現(xiàn)的詞是不是權(quán)重更大一些?

標題的詞少,但是這里的詞更能表達文章的中心思想,

?正文的詞多,但是這里的詞更不能表達文章的中心思想。

一句話:最終文檔的權(quán)重,就設(shè)定成 : 標題中出現(xiàn)的次數(shù) * 10 + 正文中出現(xiàn)的次數(shù)。

這里的權(quán)重公式可以改進。如何改進?

點擊率 = 點擊次數(shù)/展示次數(shù)

在實際開發(fā)中,比如我們的服務(wù)器,每天有一億訪問量,然后可以把這一億訪問量拆成若干份,

30%? ? ? ? 使用A公式

30%? ? ? ? 使用B公式

30%? ? ? ? 使用C公式

10%? ? ? ? 使用D公式

分別統(tǒng)計,這些情況的點擊率如何

公式會越來越復(fù)雜,同時也會讓點擊效果提升

最終我們看看這幾個公式哪個更好,就會留下哪個公式繼續(xù)迭代。

實際的搜索引擎,這里的計算公式非常復(fù)雜,并且要持續(xù)調(diào)整,反復(fù)迭代。

畫個圖理解一下倒排索引的數(shù)據(jù)結(jié)構(gòu)

站內(nèi)搜索引擎

?具體代碼實現(xiàn):

private void buildInverted(DocInfo docInfo) {
        class WordCnt {
            public int titleCount;
            public int contentCount;
        }

        HashMap<String, WordCnt> wordCntHashMap = new HashMap<>();

        List<Term> terms = ToAnalysis.parse(docInfo.getTitle()).getTerms();

        for (Term term : terms) {
            String word = term.getName();
            WordCnt wordCnt = wordCntHashMap.get(word);
            if (wordCnt == null) {
                WordCnt newWordCnt = new WordCnt();
                newWordCnt.titleCount = 1;
                wordCntHashMap.put(word, newWordCnt);
            } else {
                wordCnt.titleCount += 1;
            }

        }

        terms = ToAnalysis.parse(docInfo.getContent()).getTerms();
        for (Term term : terms) {
            String word = term.getName();
            WordCnt wordCnt = wordCntHashMap.get(word);
            if (wordCnt == null) {
                WordCnt newWordCnt = new WordCnt();
                newWordCnt.contentCount = 1;
                wordCntHashMap.put(word, newWordCnt);
            } else {
                wordCnt.contentCount += 1;
            }

        }

        for (Map.Entry<String, WordCnt> entry : wordCntHashMap.entrySet()) {
            //倒排拉鏈 invertedList
            ArrayList<Weight> invertedList = invertedIndex.get(entry.getKey());

            if (invertedList == null) {
                ArrayList<Weight> newInvertedList = new ArrayList<>();
                Weight weight = new Weight();
                weight.setDocId(docInfo.getDocId());
                weight.setWeight(entry.getValue().titleCount * 10 + entry.getValue().contentCount);
                newInvertedList.add(weight);
                invertedIndex.put(entry.getKey(), newInvertedList);
            } else {
                Weight weight = new Weight();
                weight.setDocId(docInfo.getDocId());
                weight.setWeight(entry.getValue().titleCount * 10 + entry.getValue().contentCount);
                invertedList.add(weight);
            }
        }
    }

????????

目前倒排索引構(gòu)建好了,但這些索引都保存在內(nèi)存中。而且構(gòu)建索引的過程是比較耗時間的。我們的文檔大概也有一萬多條,addDoc這個比較耗時間。

因此,我們不因該在服務(wù)器啟動的時候才構(gòu)建索引(啟動服務(wù)器會被拖慢很多很多)

我的想法是:

把這些耗時間的操作,單獨去執(zhí)行,單獨執(zhí)行完了之后,然后讓線上服務(wù)器直接加載構(gòu)造好的索引。

因此才要實現(xiàn)save和load的操作。

我們接下來就去把內(nèi)存中的索引結(jié)構(gòu),變成一個字符串,然后寫入文件,也就是序列化的過程,當我們加載文檔也就是反序列化的過程。

?序列化與反序列化也有很多方法,此處我們就用json格式來進行序列化與反序列化

我們先把jackson庫引入

站內(nèi)搜索引擎

具體實現(xiàn)代碼:

public void save() {
        System.out.println("保存索引開始!");
        File indexPathFile = new File(INDEX_PATH);
        if (!indexPathFile.exists()) {
            indexPathFile.mkdirs();
        }
        File forwardIndexFile = new File(INDEX_PATH + "forward.txt");
        File invertedIndexFile = new File(INDEX_PATH + "inverted.txt");
        try {
            objectMapper.writeValue(forwardIndexFile, forwardIndex);
            objectMapper.writeValue(invertedIndexFile, invertedIndex);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("保存索引完成!");
    }

現(xiàn)在說一下json的格式:

站內(nèi)搜索引擎

?當我們實現(xiàn)加載功能的時候,jackson庫提供了TypeReference這樣的類來幫助我們解決,json格式的數(shù)據(jù)轉(zhuǎn)換成什么類型的數(shù)據(jù),由于forwardIndex 的返回值類型是ArrayList<DocInfo>,所以進行以下編碼:

public void load() {
        System.out.println("加載索引開始!");
        File forwardIndexFile = new File(INDEX_PATH + "forward.txt");
        File invertedIndexFile = new File(INDEX_PATH + "inverted.txt");
        try {
            forwardIndex = objectMapper.readValue(forwardIndexFile, new TypeReference<ArrayList<DocInfo>>() {});
            invertedIndex = objectMapper.readValue(invertedIndexFile, new TypeReference<HashMap<String, ArrayList<Weight>>>() {});
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("加載索引結(jié)束!");
    }

現(xiàn)在我們的索引模塊基本完成了,我們看看效果,在看看能否進行一下優(yōu)化。

16.優(yōu)化運行時間

先運行一下項目:保存索引大概是560ms這個樣子,也就是save的運行時間

站內(nèi)搜索引擎

?站內(nèi)搜索引擎

文件大小第一個大約是70MB,第二個文件大小大約是64MB?

站內(nèi)搜索引擎

站內(nèi)搜索引擎

我們前邊的解析html也是比較消耗時間的,我們先寫個日志打印一下消耗的時間。

 public void run() {
        long begin = System.currentTimeMillis();
        System.out.println("索引制作開始!");
        //1.枚舉出所有的.html文件,包括子目錄中的文件
        ArrayList<File> filelist = new ArrayList<>();
        enumFile(INPUT_PATH, filelist);
        long endEnumFile = System.currentTimeMillis();
        System.out.println("枚舉文件完成!消耗時間: " + (endEnumFile - begin) + "ms");
//        System.out.println(filelist);
//        System.out.println(filelist.size());
        //2.針對上面羅列出的文檔路徑,打開文件,讀取文件內(nèi)容,進行解析,構(gòu)建索引
        for (File f : filelist) {
            System.out.println("開始解析:" + f.getAbsolutePath());
            parseHtml(f);
        }
        long endFor = System.currentTimeMillis();
        System.out.println("遍歷文件完成!消耗時間:" + (endFor - endEnumFile) + "ms");
        //3.把在內(nèi)存中構(gòu)造好的索引數(shù)據(jù)結(jié)構(gòu),保存到指定的文件中
        index.save();
        long end = System.currentTimeMillis();
        System.out.println("索引制作完成!消耗時間: " + (end - begin) + " ms");
    }

站內(nèi)搜索引擎

?可以清楚的看到制作索引需要消耗18s的時間,還是挺長的。我們該怎么辦?

說一下性能優(yōu)化:

要想優(yōu)化一段程序的性能,就需要先通過測試的手段找到其中的“性能瓶頸”?,F(xiàn)在問題主要出現(xiàn)在

 for (File f : filelist) {
            System.out.println("開始解析:" + f.getAbsolutePath());
            parseHtml(f);
        }

這一段代碼上,也就是

每次循環(huán)都要針對一個文件進行解析,讀文件+分詞+解析內(nèi)容(這里面主要還是卡在cpu運算上)

單個線程的情況下,這些任務(wù),都是串行執(zhí)行的,多個線程,這些任務(wù)就可以并發(fā)執(zhí)行了。

我們的速度就會有較大提升。

現(xiàn)在我們修改一下代碼,改成多線程制作索引。

什么時候會有線程安全問題?

多個線程同時修改一個對象,就會出現(xiàn)線程安全問題。

目前碰到一個問題,如何保證線程安全??

線程安不安全主要在parseHtml(f);這個函數(shù)

parseTitle不涉及多個線程同時修改一個對象,

parseUrl也同樣不涉及多個線程同時修改一個對象,

parseContent也不涉及多個線程同時修改一個對象,

上邊三個函數(shù)都是多個線程玩各自的對象。

問題出現(xiàn)在addDoc這個函數(shù),畫個圖理解一下。

站內(nèi)搜索引擎

八個線程同時玩forwardIndex,invertedIndex這倆個對象,勢必會出現(xiàn)線程不安全問題。

那你為啥不給addDoc加個鎖,這樣不就行了嗎?

我們引入線程的目的是為了讓串行變成并發(fā),你給addDoc加上鎖不就又成了串行執(zhí)行了嗎?

通俗點來說,脫褲子放屁,多費手續(xù)。

我們的目的是,串行的讓它并發(fā),實在并發(fā)不了的讓它串行。讓加鎖的粒度在小一些。

所以如果直接把synchronized加到parseHTML或者addDoc上,這樣做鎖的粒度太粗了,并發(fā)程度不高,就是提高的效率有限。

現(xiàn)在發(fā)現(xiàn),buildForward 和 buildInverted其實是在操作不同的對象。也就不存在鎖競爭。

新建倆個鎖對象,針對倆個鎖對象進行加鎖。

多線程的效果:

站內(nèi)搜索引擎

?多線程的使用極大的提高了,索引制作時間。

那么線程池中的線程個數(shù)設(shè)置成幾合適呢?我們只能通過實驗來進行確定。

不同的代碼并發(fā)程度是不一樣的。

并不是線程數(shù)目越多越好,線程多確實可以提升效率,但是太多的話,提升效果就不明顯了,在多加線程,白白浪費計算機資源。

目前又出現(xiàn)一個問題:

站內(nèi)搜索引擎

?程序執(zhí)行完了,進程沒有關(guān)閉。

這個問題的主要原因就是:

如果要是一個線程是守護線程,此時這個線程的運行狀態(tài),不會影響到進程結(jié)束。

如果要是一個線程不是守護線程,這個線程的運行狀態(tài),就會影響到進程結(jié)束。

默認創(chuàng)建出來的都是非守護線程,需要通過setDaemon方法手動設(shè)置,才能成為守護線程。

通過線程池創(chuàng)建的線程,并不是守護線程,

當main方法執(zhí)行完了,這些線程仍然在工作。(仍然在等待新任務(wù)的到來)

我們可以使用線程池提供的方法,讓線程停止。

目前又碰到一個問題,首次制作索引比較慢,尤其是開機之后,首次制作索引特別慢,后面就會快了,重啟機器,第一次制作就會特別慢。

通過排查parseHtml函數(shù)定位到,parseContent這個函數(shù)有問題,

計算機讀取文件,是一個開銷比較大的操作。

站內(nèi)搜索引擎

我為什么選擇atomiclong來計時間?

多線程環(huán)境下,可以簡單使用AtomicXXX 使代碼變得線程安全。?

atomiclong相當于加了synchronized的long。

開機第一次運行:

站內(nèi)搜索引擎

第二次運行:

站內(nèi)搜索引擎

可以明顯看到,t1的時間變化,????

站內(nèi)搜索引擎????

注意此處是八個線程累加的時間。?

(第一次開機運行,t2用了51s ,第二次運行t2用了25s,搞不懂為啥出現(xiàn)這種情況)

這種情況的話,我猜測是因為addDoc之前,你就得把title,url,content解析出來,parsecontent沒解析完,adddoc就得等著,t2的時間前后也是2倍關(guān)系。

接下來我們可以優(yōu)化一下parsecontent這個函數(shù)。

    public String parseContent(File f) {
        try (FileReader fileReader = new FileReader(f)) {
            StringBuilder content = new StringBuilder();
            while (true) {
                int ret = fileReader.read();
                if (ret == -1) {
                    break;
                }
                char c = (char) ret;
                content.append(c);
            }

我們讀取文件用的是FileReader這個方法,fileReader.read()每次從文件中讀取一個字符,每次read都是在讀磁盤,它的速度就會很慢。

思路:我們可以先讓filereader提前把文件讀取到內(nèi)存里面,然后每次調(diào)用一次bufferedReader.read() 就可以從內(nèi)存中讀取.

BufferedReader 可以搭配FileReader來使用。

BufferedReader內(nèi)部就會內(nèi)置一個緩沖區(qū)。就能夠自動的把FileReader中的一些內(nèi)容預(yù)讀到內(nèi)存中,從而減少直接訪問磁盤的次數(shù)。

其實FileReader也有緩沖區(qū),只是BufferedReader對緩沖支持更好。

此刻的心情:優(yōu)化了個寂寞。

但是,開機第一次運行的效果肯定比沒優(yōu)化前好,我們開機重新試一下。

站內(nèi)搜索引擎

此時用了19秒?比前開機少用了10來秒,只能說還行。

17.實現(xiàn)搜索模塊

首先,搜索模塊就是調(diào)用索引模塊,來完成搜索的核心過程~

1.分詞。針對用戶輸入的詞/句進行分詞

2.觸發(fā),拿著每個分詞結(jié)果,去倒排索引中查,找到具有相關(guān)性的文檔,

3.排序,針對上邊觸發(fā)出來的結(jié)果,進行排序(按照相關(guān)性,降序排序)

4.包裝結(jié)果。根據(jù)排序后的結(jié)果,依次去查正排,獲取到每個文檔的詳細信息,包裝成一定的數(shù)據(jù)結(jié)構(gòu)返回出去。

目前遇到一個問題,返回結(jié)果中的描述該如何返回?

我們只是得到了正文。

說一下描述包含什么?描述是正文的一段摘要,這個摘要來源于正文,同時要包含查詢詞或者查詢詞的一部分。

思路:

目前我們可以獲取所有的查詢詞的分詞結(jié)果

站內(nèi)搜索引擎

遍歷分詞結(jié)果,看看哪個結(jié)果在正文中出現(xiàn)

for (Weight weight : allTermTesult) {
            DocInfo docInfo = index.getDocInfo(weight.getDocId());
            Result result = new Result();
            result.setTitle(docInfo.getTitle());
            result.setUrl(docInfo.getUrl());
            result.setDesc(GenDesc(docInfo.getContent(), terms));
            results.add(result);
        }

這里抽象出了一個方法GenDesc,根據(jù)正文和分詞結(jié)果來生成描述。

針對當前文檔來說,不一定包含所有的分詞結(jié)果

就針對這個被包含的分詞結(jié)果,去正文中查找,找到對應(yīng)的位置

就以這個詞的位置為中心,往前截取60個字符,作為描述的開始。

然后再從這個描述開始,截取160個字符,作為整個描述。

如果用戶查詢的時候輸入了Hello,我們的分詞結(jié)果都是小寫的,所以用戶不管輸入什么,都會被轉(zhuǎn)換成小寫字母,那么正文中的大寫字母也得轉(zhuǎn)換成小寫字母,不然就查不到。我們這里統(tǒng)一弄成小寫的。

private String GenDesc(String content, List<Term> terms) {
        int firstPos = -1;
        for (Term term : terms) {
            String word = term.getName();
            firstPos = content.toLowerCase().indexOf(word);
            if (firstPos >= 0) {
                //找到了位置
                break;
            }
        }
    }

還有一個問題,如果用戶輸入的查詢詞是List,而正文中出現(xiàn)的是ArrayList,在生成描述的時候,此處拿著這個List去正文中indexOf,此時是否會把ArrayList當作結(jié)果呢?

這就會導致生成的描述,里面就是帶ArrayList的,而不是帶List的了

我要查List結(jié)果描述里邊是ArrayList 和 List,這樣設(shè)計就不科學。

類似這樣的情況,在查倒排的時候,是否會存在呢?

倒排索引中的key都是分詞結(jié)果,ArrayList不會被分成Array + List ,仍然把ArrayList視為是一個單詞。List和ArrayList并不能匹配,使用List這個詞不能查出包含ArrayList的結(jié)果。這是科學的

因此我們希望,在生成描述的過程中能夠找到整個詞都匹配的結(jié)果,才算是找到了。而不是只找到詞的一部分。

如何讓word獨立成詞?而不是只作為正文詞的一部分。

站內(nèi)搜索引擎

我的想法是直接在word的前后加個空格,讓這個詞獨立出來。

站內(nèi)搜索引擎

?僅僅是這么一處代碼,卻需要思考這么多的東西。

驗證一下docsearcher類

站內(nèi)搜索引擎

?站內(nèi)搜索引擎

結(jié)果符合我們的預(yù)期要求。?

18.實現(xiàn)web模塊

提供一個web接口,最終以網(wǎng)頁的形式,把我們的程序呈現(xiàn)給用戶。

前端(html+css+js)后端(servlet/spring)先用servlet實現(xiàn),在升級成spring

現(xiàn)在約定一下前后端的通信接口。

請求:

GET/searcher?query=[查詢詞] HTTP/1.1

響應(yīng):(json格式的數(shù)據(jù))

Http/1.1 200 ok

[

? ? ? ? {

? ? ? ? ? ? ? ? title:"這是標題1",

? ? ? ? ? ? ? ? url:"這是url1",

? ? ? ? ? ? ? ? desc:"這是描述1",

????????},

? ? ? ? {?? ??

????????????????title:"這是標題2",

? ? ? ? ? ? ? ? url:"這是url2",

? ? ? ? ? ? ? ? desc:"這是描述2",

? ? ? ? },

]

具體實現(xiàn):

package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import searcher.DocSearcher;
import searcher.Result;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class DocSearcherServlet extends HttpServlet {
    //全局唯一,用static修飾一下
    private static DocSearcher docSearcher = new DocSearcher();
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //拿到用戶提交的查詢詞
        String query = req.getParameter("query");
        if (query == null || query.equals("")) {
            String msg = "您的參數(shù)非法,沒有獲取到query的值!";
            System.out.println(msg);
            resp.sendError(404, msg);
            return;
        }

        System.out.println("query=" + query);

        List<Result> results = docSearcher.search(query);

        //把結(jié)果進行打包
        resp.setContentType("application/json;charset=utf-8");

        objectMapper.writeValue(resp.getWriter(),results);

    }
}

驗證一下效果:

站內(nèi)搜索引擎

后端這邊我們已經(jīng)做好了,我們接下來做一個好看點的前端頁面。

19.前端頁面的制作?

我們利用ajax進行前后端交互,

當用戶點擊搜索按鈕的時候,瀏覽器就會獲取到搜索框的內(nèi)容,基于ajax構(gòu)造HTTP請求,然后發(fā)給搜索服務(wù)器。瀏覽器獲取到搜索結(jié)果之后,在根據(jù)結(jié)果的json數(shù)據(jù),把頁面生成出來。

目前遇到一個巨坑,嗚嗚嗚~調(diào)試了2個小時終于讓我給逮住了。

站內(nèi)搜索引擎

ajax構(gòu)造請求的路徑?jīng)]有理清楚,造成時間上的浪費。

站內(nèi)搜索引擎

我把index.?html放在了html這個文件夾中,所以ajax構(gòu)造請求url的路徑得修改一下,

站內(nèi)搜索引擎

?如果我放在webapp下,就不用加../了

我是看了這個博客解決的:

ajax關(guān)于url路徑問題

目前又遇到一個問題:

站內(nèi)搜索引擎

內(nèi)容太多,超出了一個屏幕,該怎么解決?

可以通過修改css代碼,

你可以定位到代碼問題出現(xiàn)在哪里嗎?

最大的div類名是container.,就讓在這個div內(nèi)部滾動。

站內(nèi)搜索引擎

又遇到一個問題:

第一次搜索和第二次搜索結(jié)果會累加到一起

站內(nèi)搜索引擎

?站內(nèi)搜索引擎

出現(xiàn)這個問題的原因是啥?

?每次點擊按鈕,都是把結(jié)果往.result里面進行追加,沒有清理過內(nèi)容

更科學的方法,應(yīng)該是在每次搜索之前,都把之前的舊的結(jié)果給清空掉。

現(xiàn)在我們在實現(xiàn)一下標紅邏輯。

1.修改后端代碼,生成搜索結(jié)果的時候,就需要把其中包含查詢詞的部分,給加上一個標記。

例如,給這個部分套上一層<i>標簽~

2.然后在前端這里針對<i>標簽設(shè)置樣式,然后瀏覽器就可以根據(jù)<i>標簽的樣式來進行顯示了,

(比如給<i>標簽的字體顏色設(shè)置為紅色即可)

具體實現(xiàn):

private String GenDesc(String content, List<Term> terms) {
        int firstPos = -1;
        for (Term term : terms) {
            String word = term.getName();
            firstPos = content.toLowerCase().indexOf(" " + word + " ");
            if (firstPos >= 0) {
                //找到了位置
                break;
            }
        }

        if (firstPos == -1) {
            //所有的分詞結(jié)果都不在正文中存在 我們返回空的描述就不合適,所以我們返回正文的前160個字符
            return content.substring(0, 160) + "...";
        }

        //
        String desc = "";
        int descBeg = firstPos < 60 ? 0 : firstPos - 60;
        if (descBeg + 160 > content.length()) {
            desc = content.substring(descBeg);//從起始位置截到末尾
        } else {
            desc = content.substring(descBeg, descBeg + 160) + "...";
        }

        for (Term term : terms) {
            String word = term.getName();
            //此處進行全字匹配,也就是當查詢詞為list的時候不能把Arraylist中的List給單獨標紅。(?i) 不區(qū)分大小寫替換
            desc = desc.replaceAll("(?i) " + word + " ", "<i> " + word + " </i>");
        }
        return desc;
    }

站內(nèi)搜索引擎

現(xiàn)在測試一下更加復(fù)雜的情況:

站內(nèi)搜索引擎

站內(nèi)搜索引擎

?倆次的搜索結(jié)果一樣,

站內(nèi)搜索引擎

服務(wù)器500,原因是代碼執(zhí)行過程中拋出異常了。

就需要找到?

站內(nèi)搜索引擎

?站內(nèi)搜索引擎

?數(shù)組越界異常:

排查發(fā)現(xiàn)如果正文沒有160個字符,還要截取160個字符必然會導致錯誤。

站內(nèi)搜索引擎

改正:

站內(nèi)搜索引擎

站內(nèi)搜索引擎

站內(nèi)搜索引擎

又出現(xiàn)一個問題:

下邊的itemDiv都沒有標紅的字?

?我想是因為分詞把空格也看成一個詞了,導致代碼會拿空格去查找倒排索引,我們想個辦法把空格去掉。

這里用停用詞表,修改一下代碼。

站內(nèi)搜索引擎

思路:

讓搜索程序加載這個停用詞表,到內(nèi)存中,

使用一個HashSet把這些詞都存起來,

在針對分詞結(jié)果,在停用詞中進行篩選,

如果某個結(jié)果在詞表中存在,就直接去掉。

驗證結(jié)果:

站內(nèi)搜索引擎

符合預(yù)期要求。?

又發(fā)現(xiàn)一個bug

站內(nèi)搜索引擎

還是有不標紅的情況,出現(xiàn)這種情況的原因

站內(nèi)搜索引擎

我點進去一個不標紅的文檔,搜索關(guān)鍵字,結(jié)果發(fā)現(xiàn)該文檔確實存在這個關(guān)鍵字,哪里出現(xiàn)了問題?

站內(nèi)搜索引擎

前邊后邊都有空格才去匹配這個firstPos,那要是沒有空格就匹配不到了,關(guān)鍵是全文就只有這一個字?,所以firstPos直接返回的是-1,我們要解決這里的問題,就得使用正則表達式。

站內(nèi)搜索引擎

站內(nèi)搜索引擎

站內(nèi)搜索引擎

站內(nèi)搜索引擎

成功解決bug。

目前又發(fā)現(xiàn)一個問題:

站內(nèi)搜索引擎

站內(nèi)搜索引擎

站內(nèi)搜索引擎

1576 + 1350? = 2926 = 2926

站內(nèi)搜索引擎

同一個文檔即出現(xiàn)了array 又出現(xiàn)了list,也就是說,ArrayList出現(xiàn)了倆次,重復(fù)了。

前面算權(quán)重,針對分詞結(jié)果依次進行促發(fā),

array => 觸發(fā)一組docId

list => 觸發(fā)一組docId?

同時包含多個分詞結(jié)果,意味著這個文檔的相關(guān)性更高,

像這種情況,就應(yīng)該提高這個文檔的權(quán)重,既然相關(guān)性更高,提高權(quán)重之后就能排的更靠前。

把權(quán)重進行相加。把多個分詞結(jié)果觸發(fā)的文檔,按照docId進行去重,同時進行權(quán)重合并。

去重思路:?

合并倆個有序列表,合并倆個數(shù)組。

先把分詞結(jié)果進行一個排序處理(按照docId升序排序)在進行合并,合并的時候就可以根據(jù)docId值相同的情況,做權(quán)重相加。

可是用戶輸入的僅僅就是倆個詞嗎?

所以應(yīng)該是N個數(shù)組合并。

對比多個數(shù)組值的大小關(guān)系,找到小的,插入到結(jié)果中。

站內(nèi)搜索引擎

誰對應(yīng)的值越小,就把這個值取出來,插入到結(jié)果數(shù)組中 ,同時針對這個下標進行++。

我們這里使用堆/優(yōu)先級隊列?

站內(nèi)搜索引擎

end.擴散一下思維,那么一些小型網(wǎng)站的搜索引擎我們是否就會做了呢?

我們是否還能通過es來做一下?

爬蟲能否實現(xiàn)一下?文章來源地址http://www.zghlxwxcb.cn/news/detail-410636.html

到了這里,關(guān)于站內(nèi)搜索引擎的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • [C++項目] Boost文檔 站內(nèi)搜索引擎(4): 搜索的相關(guān)接口的實現(xiàn)、線程安全的單例index接口、cppjieba分詞庫的使用、綜合調(diào)試...

    [C++項目] Boost文檔 站內(nèi)搜索引擎(4): 搜索的相關(guān)接口的實現(xiàn)、線程安全的單例index接口、cppjieba分詞庫的使用、綜合調(diào)試...

    有關(guān) Boost 文檔搜索引擎的項目的前三篇文章, 已經(jīng)分別介紹分析了: 項目背景: ??[C++項目] Boost文檔 站內(nèi)搜索引擎(1): 項目背景介紹、相關(guān)技術(shù)棧、相關(guān)概念介紹… 文檔解析、處理模塊 parser 的實現(xiàn): ??[C++項目] Boost文檔 站內(nèi)搜索引擎(2): 文檔文本解析模塊parser的實現(xiàn)、如何對

    2024年02月14日
    瀏覽(28)
  • [C++項目] Boost文檔 站內(nèi)搜索引擎(2): 文檔文本解析模塊parser的實現(xiàn)、如何對文檔文件去標簽、如何獲取文檔標題...

    [C++項目] Boost文檔 站內(nèi)搜索引擎(2): 文檔文本解析模塊parser的實現(xiàn)、如何對文檔文件去標簽、如何獲取文檔標題...

    在上一篇文章中, 已經(jīng)從 Boost 官網(wǎng)獲取了 Boost 庫的源碼. 相關(guān)文章: ??[C++項目] Boost文檔 站內(nèi)搜索引擎(1): 項目背景介紹、相關(guān)技術(shù)棧、相關(guān)概念介紹… 接下來就要編寫代碼了. 不過還需要做一些準備工作. 創(chuàng)建項目目錄 所有的項目文件肯定要在一個目錄下, 找一個位置執(zhí)行下

    2024年02月14日
    瀏覽(25)
  • [C++項目] Boost文檔 站內(nèi)搜索引擎(3): 建立文檔及其關(guān)鍵字的正排 倒排索引、jieba庫的安裝與使用...

    [C++項目] Boost文檔 站內(nèi)搜索引擎(3): 建立文檔及其關(guān)鍵字的正排 倒排索引、jieba庫的安裝與使用...

    之前的兩篇文章: 第一篇文章介紹了本項目的背景, 獲取了 Boost 庫文檔 ??[C++項目] Boost文檔 站內(nèi)搜索引擎(1): 項目背景介紹、相關(guān)技術(shù)棧、相關(guān)概念介紹… 第二篇文章 分析實現(xiàn)了 parser 模塊. 此模塊的作用是 對所有文檔 html 文件, 進行清理并匯總 ??[C++項目] Boost文檔 站內(nèi)搜

    2024年02月07日
    瀏覽(91)
  • 什么是搜索引擎?2023 年搜索引擎如何運作?

    什么是搜索引擎?2023 年搜索引擎如何運作?

    在當今的數(shù)字時代,搜索引擎已經(jīng)成為人們獲取信息的主要途徑之一。然而,你是否知道搜索引擎是如何工作的,以及它們?yōu)槭裁慈绱酥匾?搜索引擎是一種計算機程序,通過互聯(lián)網(wǎng)或企業(yè)內(nèi)部網(wǎng)絡(luò)檢索信息。用戶輸入或短語后,搜索引擎會掃描網(wǎng)絡(luò)上的網(wǎng)頁、文件、

    2024年02月16日
    瀏覽(23)
  • Elasticsearch:什么是搜索引擎?

    Elasticsearch:什么是搜索引擎?

    搜索引擎是一種軟件程序或系統(tǒng),旨在幫助用戶查找存儲在互聯(lián)網(wǎng)或特定數(shù)據(jù)庫中的信息。 搜索引擎的工作原理是對各種來源的內(nèi)容進行索引和編目,然后根據(jù)用戶的搜索查詢向用戶提供相關(guān)結(jié)果列表。 搜索引擎對于希望快速有效地查找特定信息的用戶來說是有用的工具。

    2024年02月21日
    瀏覽(25)
  • 除了百度還有什么搜索引擎比較好

    除了百度還有什么搜索引擎比較好

    百度是國內(nèi)最大的搜索引擎,也是國內(nèi)最好的搜索引擎。但是由于其廣告比較多,有些同學不太喜歡使用百度搜索。那么除了百度還有什么搜索引擎比較好?小編就來和大家分享幾款國內(nèi)可以使用的其他搜索引擎。 1.谷歌搜索,谷歌搜索是全球最受歡迎的搜索引擎,在國內(nèi)無法

    2024年02月11日
    瀏覽(24)
  • 為什么選擇elasticsearch分布式搜索引擎

    為什么選擇elasticsearch分布式搜索引擎

    elasticsearch是一款非常強大的開源搜索引擎,具備非常多強大功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內(nèi)容 例如: 在CSDN上搜索代碼 在電商網(wǎng)站搜索商品 在百度搜索答案 elasticsearch結(jié)合kibana、Logstash、Beats,也就是elastic stack(ELK)。被廣泛應(yīng)用在日志數(shù)據(jù)分析、實時監(jiān)

    2024年02月12日
    瀏覽(22)
  • 【迅搜02】究竟什么是搜索引擎?正式介紹XunSearch

    啥?還要單獨講一下啥是搜索引擎?不就是百度、Google嘛,這玩意天天用,還輪的到你來說? 額,好吧,雖然大家天天都在用,但是我發(fā)現(xiàn),其實很多人對搜索引擎并不是特別了解,更別提搜索引擎開發(fā)了。不信?那么咱們就一步一步來看。 上來先官方,看看百科中對搜索

    2024年02月05日
    瀏覽(20)
  • 為什么說ChatGPT還不是搜索引擎的對手

    1950年,英國科學家圖靈在一篇論文中預(yù)言,人類有可能創(chuàng)造出具有真正智能的機器。 著名的「圖靈測試」就此誕生:如果一臺機器能夠與人類展開對話,而不被辨別出其機器身份,那么稱這臺機器具有智能。 也是從那時開始,人類世界開始了對人工智能長達半個多世紀的探

    2024年02月11日
    瀏覽(24)
  • 什么是搜索引擎(SEO)爬蟲&它們是如何工作的?

    什么是搜索引擎(SEO)爬蟲&它們是如何工作的?

    你的網(wǎng)站上有蜘蛛???。別抓狂!我說的不是真正的八條腿的蜘蛛???。 我指的是搜索引擎優(yōu)化爬蟲。他們是實現(xiàn)SEO的機器人。每個主要的搜索引擎都使用爬蟲來對可感知的互聯(lián)網(wǎng)進行分類。正是通過這些爬蟲(有時被稱為爬行爬蟲或爬行器)的工作,你的網(wǎng)站才在谷歌、

    2024年04月09日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包