boost搜索引擎

作者 : admin 本文共20744个字,预计阅读时间需要52分钟 发布时间: 2024-06-10 共3人阅读

文章目录

  • boost搜索引擎的意义
  • 技术栈与项目环境
  • 搜索引擎的原理
    • 暂停词
    • 正排索引(Forward Index)
    • 倒排索引(Inverted Index)
  • 数据去标签化
    • 去标签
    • 常用工具类
    • 添加日志
  • 索引的建立
    • 正排索引的建立
    • 倒排索引的建立
  • 搜索引擎的构成
    • **初始化**
    • **查询处理**
    • **简介生成**
  • 前端网页
    • 查询输入
    • 搜索以及结果展示
    • 分页控制
    • CSS样式
  • HTTP服务
    • 工作流程概述
    • 部署服务器
  • 项目展示
    • 启动页面
    • 搜索结果页面

boost搜索引擎的意义

boost库是为C++语言标准库提供扩展的一些C++程序库的总称,由Boost社区组织开发、维护。Boost库可以与C++标准库完美共同工作,并且为其提供扩展功能。boost网站提供了大量的文档,实现一个搜索引擎可以帮助我们在大量的文档中准确快速找到自己所需求的文档。

技术栈与项目环境

  • 技术栈

后端:C/C++、C++11、STL、准标准库Boost、Jsoncpp、cppjieba、cpp-httplib

前端:html5、css、js、jQuery、Ajax

  • 项目环境

Centos7、vim、gcc(g++)/Makefile、vscode

(项目gitee仓库)

搜索引擎的原理

搜索大量的文档以及文档中包含的内容,显然是非常耗时耗力的一种行为。如果直接去一个个去遍历访问,基本会导致服务长时间得不到响应。为此需要更见快速以及便捷的方式去规划和管理大量的数据,实现快速查找,建立索引是解决这个问题的核心。

所谓的索引,就是将文档贴上一个标签,根据标签去快速查找。管理标签相对于管理文档的压力要小很多,这是建立索引的本质原因。

暂停词

暂停词(Stop Words)是指在自然语言处理中(NLP)和信息检索中,为了提高处理效率和效果而被忽略或移除的常见词语。这些词通常是高频率出现但对文档内容或语义贡献不大的词汇。

特点

  1. 高频率出现:暂停词在文档中出现频率非常高,例如英语中的 “the”, “is”, “in”, “and”,以及中文中的 “的”, “了”, “在” 等。
  2. 低语义贡献:暂停词对文档内容的实际语义贡献较小,通常不能用来区分不同的文档。

作用

  1. 减少数据处理量:通过移除暂停词,可以显著减少要处理的词汇数量,从而提高处理速度和效率。
  2. 提升检索效果:暂停词的移除可以减少噪声,提升信息检索系统的查询结果的相关性和精确度。

正排索引(Forward Index)

正排索引,也称为正向索引,是将文档与其包含的词汇进行关联的索引结构。每个文档都包含一个词汇列表及其在文档中的位置信息。

原理

文档级别:每个文档都有一个唯一的标识符(如DocID)。

词汇表:每个文档包含一个词汇表,记录了该文档中的所有词汇及其位置。

例如,有两个文档如下:

文档ID文档内容
1苹果的电脑
2苹果的手机

去掉暂停词之后,正排索引可以表示为:

文档ID文档内容
1苹果 电脑
2苹果 手机

优点

  • 易于理解和构建。
  • 适合小规模数据的全文检索。

缺点

  • 查询效率低。要查找某个词语出现在哪些文档中,需要遍历所有文档的词汇表。

倒排索引(Inverted Index)

倒排索引也称为反向索引,是将词汇与其所在的文档进行关联的索引结构。每个词汇都关联一个包含该词汇的文档列表及其位置。

原理

词汇级别:每个词汇都有一个唯一的标识符。

文档列表:每个词汇包含一个文档列表,记录了该词汇出现的所有文档及其位置。

例如,有两个文档如下:

文档ID文档内容
1苹果的电脑
2苹果的手机

去掉暂停词之后,倒排索引可以表示为:

关键字(具有唯一性)文档ID
苹果1、2
电脑1
手机2

使用倒排索引,此时用户搜索苹果,则会通过索引找到文档1和2。用户搜索电脑,则会找到文档1。

优点

  • 查询效率高。可以快速查找到包含某个词汇的所有文档。
  • 适合大规模数据的全文检索。

缺点

  • 构建和维护复杂度高。需要处理大量数据和存储空间。(用户友好型)

数据去标签化

去标签

本项目的文档搜索范围均为html文件,均在http://www.boost.org/doc/libs/1_85_0/doc/html路径下,其中1_85_0是boost库的版本。

如下是该路径下的一个文件内容http://www.boost.org/doc/libs/1_85_0/doc/html/tools.html:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Chapter 1. Boost.Accumulators - 1.85.0</title>
<link rel="stylesheet" href="../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="libraries.html" title="Part I. The Boost C++ Libraries (BoostBook Subset)">
<link rel="prev" href="libraries.html" title="Part I. The Boost C++ Libraries (BoostBook Subset)">
<link rel="next" href="accumulators/user_s_guide.html" title="User's Guide">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/favicon.ico" type="image/ico"/><link rel="stylesheet" type="text/css" href="/style-v2/section-basic.css"/></head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">  <div id="boost-common-heading-doc">
<div class="heading-inner">
<div class="heading-placard"></div>
<h1 class="heading-title">
<a href="/">
<img src="/gfx/space.png" alt= "Boost C++ Libraries" class="heading-logo" />
<span class="heading-boost">Boost</span>
<span class="heading-cpplibraries">C++ Libraries</span>
</a></h1>
......
</body>
</html>

文件中的形如、


等处于两个小尖括号之间的是html的语法,本就是不需要的内容。这些标签一般成对出现,形如……。去标签化就是删除这些没有用处的信息,只保留下该html文件在网页所呈现的文字内容。

最终的效果:将每一个文档的标签删除,得到的内容放到一个网页正文文件的一行。

  • 步骤1 读取html文件内容
  • 步骤2 获取文档的标题、正文、URL
  • 步骤3 将获取的信息连接成一行数据,写入网页正文文件。

代码如下

parser.cc:

#include
#include 
#include 
#include 
#include "util.hpp"
#include "log.hpp"
//所有的html网页的路径
const std::string src_path="data/input";
//输出文件的路径
const std::string output = "data/raw_html/raw.txt";
//每个文件的解析信息
typedef struct DocInfo
{
std::string title;//文档的标题
std::string content;//文档的主体
std::string url;//文档网页的链接
}DocInfo_t;
//遍历文档
bool EnumFile(const std::string &src_path, std::vector* file_path_list);
//去标签化
bool ParseHtml(const std::vector &file_path_list, std::vector* results);
//保存文档
bool SaveHtml(const std::vector &results, const std::string &output);
int main()
{
std::vector file_path_list;
//第一步,递归式的把每个html文件名和路径保存到file_path_list
if(!EnumFile(src_path,&file_path_list))
{
std::cerr<<"enum file error!"<<std::endl;
return 1;
}
//第二步,读取每个文件的内容,并进行解析
std::vector results;
if(!ParseHtml(file_path_list,&results))
{
std::cerr<<"parse html error"<<std::endl;
return 2;
}
//第三步,把解析完毕的各个文件内容,输入到output
if(!SaveHtml(results,output))
{
std::cerr<< "save html error"<<std::endl;
return 3;
}
return 0;
}
bool EnumFile(const std::string &src_path, std::vector* file_path_list)
{
namespace fs = boost::filesystem;
fs::path root_path(src_path);
//判断路径是否存在
if(!fs::exists(root_path))
{
std::cerr<< src_path <<" not exists"<path().extension()!=".html")
{
continue;
}
file_path_list->push_back(iter->path().string());
}
return true;
}
static bool ParseTitle(const std::string& file,std::string* title)
{
std::size_t begin=file.find("");
if(begin==std::string::npos)
{
return false;
} 
std::size_t end=file.find("");
if(end==std::string::npos)
{
return false;
}
begin+=std::string("").size();
if(begin>end)
{
return false;
}
*title = file.substr(begin,end-begin);
return true;
}
static bool ParseContent(const std::string& file, std::string* content)
{
enum status
{
LABLE,
CONTENT
};
enum status s = LABLE;
for(char c : file)
{
switch(s)
{
case LABLE:
if(c=='>') s=CONTENT;
break;
case CONTENT:
if(c=='push_back(c);
}
break;
default:
break;
}
}
return true;
}
static bool PaserUrl(const std::string& file_path, std::string* url)
{
std::string url_head = "http://www.boost.org/doc/libs/1_85_0/doc/html";
std::string url_tail = file_path.substr(src_path.size());
*url=url_head+url_tail;
return true;
}
bool ParseHtml(const std::vector &file_path_list, std::vector* results)
{
for(const std::string &file : file_path_list)
{
std::string result;
//1.读取文件。Read()
if(!ns_util::FileUtil::ReadFile(file,&result))
{
continue;
}
//2.解析指定的文件,提取title
DocInfo_t doc;
if(!ParseTitle(result,&doc.title))
{
continue;
}
//3.解析指定的文件,提取content
if(!ParseContent(result,&doc.content))
{
continue;
}
//4.解析指定的文件路径,构建URL
if(!PaserUrl(file,&doc.url))
{
continue;
}
results->push_back(std::move(doc));
}
return true;
}
bool SaveHtml(const std::vector &results, const std::string &output_file_path)
{
#define SEP '\3'
//保存形式title\3content\3url
std::ofstream out(output_file_path,std::ios::out | std::ios::binary);
if(!out.is_open())
{
std::cerr << "oean "<<output_file_path <<" failed"<<std::endl;
}
//文件内容写入
for(auto &item : results)
{
std::string line=item.title;
line+=SEP;
line+=item.content;
line+=SEP;
line+=item.url;
line+='
';
out.write(line.c_str(),line.size());
}
out.close();
return true;
}
</code></pre><p>其中涉及到的util.hpp以及log.hpp分别是常用分词工具以及日志功能。</p><h3>常用工具类</h3><p>util.hpp:</p><pre><code class="prism language-c++">#pragma once
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "cppjieba/Jieba.hpp"
#include "log.hpp"
namespace ns_util
{
class FileUtil
{
public:
static bool ReadFile(const std::string& file_path, std::string* out)
{
std::ifstream in(file_path,std::ios::in);
if(!in.is_open())
{
std::cerr<<"open file "<<file_path<<"error"<<std::endl;
return false;
}
std::string line;
while(std::getline(in,line))
{
*out+=line;
}
in.close();
return true;
}
};
class StringUtil
{
public:
static void Split(const std::string& target, std::vector *out,std::string sep)
{
boost::split(*out,target,boost::is_any_of(sep),boost::token_compress_on);
}
};
const char* const DICT_PATH = "./dict/jieba.dict.utf8";
const char* const HMM_PATH = "./dict/hmm_model.utf8";
const char* const USER_DICT_PATH = "./dict/user.dict.utf8";
const char* const IDF_PATH = "./dict/idf.utf8";
const char* const STOP_WORD_PATH = "./dict/stop_words.utf8"; 
class JiebaUtil
{
private:
JiebaUtil():jieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH){}
JiebaUtil(const JiebaUtil&)=delete;
JiebaUtil& operator=(const JiebaUtil&)=delete;
static JiebaUtil *instance;
public:
static JiebaUtil* GetInstance()
{
static std::mutex mtx;
if(nullptr==instance)
{
mtx.lock();
if(nullptr==instance)
{
instance = new JiebaUtil();
instance->InitJiabaUtil();
}
mtx.unlock();
}
return instance;
}
void InitJiabaUtil()
{
std::ifstream in(STOP_WORD_PATH);
if(!in.is_open())
{
LOG(FATAL,"加载暂停词文件失败");
return;
}
std::string line;
while(std::getline(in,line))
{
stop_words.insert({line,true});
}
in.close();
}
void CutStringHelper(const std::string &src,std::vector*out)
{
jieba.CutForSearch(src,*out);
for(auto iter=out->begin();iter!=out->end();){
auto it = stop_words.find(*iter);
if(it!=stop_words.end())
{
iter=out->erase(iter);
}else{
iter++;
}
}
}
public:
static void CutString(const std::string &src,std::vector*out)
{
ns_util::JiebaUtil::GetInstance()->CutStringHelper(src,out);
}
private:
cppjieba::Jieba jieba;
std::unordered_map stop_words;
};
JiebaUtil *JiebaUtil::instance=nullptr;
}
</code></pre><p><code>FileUtil</code> 类</p><ul><li><code>ReadFile</code> 方法:读取文件内容,并将其存储到 <code>out</code> 字符串中。如果文件无法打开,则返回 <code>false</code> 并输出错误信息。</li></ul><p><code>StringUtil</code> 类</p><ul><li><code>Split</code> 方法:使用 Boost 库的 <code>split</code> 函数,根据指定的分隔符 <code>sep</code> 将目标字符串 <code>target</code> 分割成多个子字符串,并存储在 <code>out</code> 向量中。</li></ul><p><code>JiebaUtil</code> 类</p><ul><li><p><strong>单例模式</strong>:通过私有构造函数和静态指针 <code>instance</code> 实现单例模式,确保 <code>JiebaUtil</code> 类只有一个实例。</p></li><li><p><strong>初始化</strong>:</p><ul><li><code>JiebaUtil()</code> 构造函数:初始化 Jieba 分词器,加载相关词典。</li><li><code>InitJiebaUtil</code> 方法:加载暂停词(Stop Words)文件,将暂停词存储在 <code>stop_words</code> 哈希表中。</li></ul></li><li><p><strong>分词功能</strong>:</p><ul><li><code>CutStringHelper</code> 方法:使用 Jieba 的 <code>CutForSearch</code> 方法进行分词,并移除暂停词。</li></ul></li><li><p><code>CutString</code> 方法:对外提供分词接口,调用 <code>CutStringHelper</code>。</p></li></ul><h3>添加日志</h3><p>log.hpp:</p><pre><code class="prism language-c++">#pragma once
#include 
#include 
#include 
#include 
#include 
#include 
#include 
// 日志级别枚举
enum LogLevel {
NORMAL,
WARNING,
DEBUG,
FATAL
};
// 日志宏定义
#define LOG(LEVEL, MESSAGE) log(LEVEL, MESSAGE, __FILE__, __LINE__)
std::mutex logMutex;
// 获取当前时间的格式化字符串
std::string getCurrentTime() {
std::time_t now = std::time(nullptr);
std::tm* localTime = std::localtime(&now);
std::ostringstream timeStream;
timeStream << std::put_time(localTime, "%Y-%m-%d %H:%M:%S");
return timeStream.str();
}
// 将日志级别枚举转换为字符串
std::string logLevelToString(LogLevel level) {
switch(level) {
case NORMAL: return "NORMAL";
case WARNING: return "WARNING";
case DEBUG: return "DEBUG";
case FATAL: return "FATAL";
default: return "UNKNOWN";
}
}
// 日志记录函数
void log(LogLevel level, const std::string& message, const std::string& file, int line) {
std::lock_guard guard(logMutex); // 保证线程安全
std::string currentTime = getCurrentTime();
std::cout << "[" << currentTime << "]"
<< "[" << logLevelToString(level) << "]"
<< "[" << message << "]"
<< "[" << file << " : " << line << "]" << std::endl;
}
</code></pre><h2>索引的建立</h2><p>根据已经去标签之后的数据,逐行获取每个文档的信息,分别建立正排索引以及倒排索引。正排索引是用来根据文档的id获取文档的内容,而倒排索引是用来进行快速搜索,在搜索模块会用到。</p><h3>正排索引的建立</h3><p>正排索引是文档id与文档内容的一对一映射关系,因此可以使用vector的数据结构来表示。</p><pre><code class="prism language-c++">struct DocInfo
{
std::string title;//文档的标题
std::string content;//文档的主体
std::string url;//文档网页的链接
std::uint64_t doc_id; //文档的ID
};
std::vector forward_index;//正排索引
</code></pre><p>可以遍历网页正文文件的每一行,文档ID就是行号,也可以是加入正排索引前正排索引的大小。</p><pre><code class="prism language-c++">DocInfo* BuildForwardIndex(const std::string &line)
{
//1.解析line,进行字符串切分
std::vector results;
const std::string sep= "\3";
ns_util::StringUtil::Split(line,&results,sep);
if(results.size()!=3)
{
return nullptr;
}
//2.字符串进行填充到Docinfo
DocInfo doc;
doc.title=results[0];
doc.content=results[1];
doc.url=results[2];
doc.doc_id=forward_index.size();
//3.插入到正排索引的vector
forward_index.push_back(std::move(doc));
return &forward_index.back();
}
</code></pre><h3>倒排索引的建立</h3><p>倒排索引用于搜索功能的实现,根据关键字,获取对应的文档ID,再通过文档ID结合正排索引,获得文档的内容。此时关键字对应的文档ID的个数很有可能有多个,形成一个拉链(顾名思义就是一串的文档ID)。但是光有文档ID是不够的,搜索所呈现出来的结果要有排列的顺序,因此需要对每一ID附加一个权重值,方便对查询结果进行排序。</p><pre><code class="prism language-c++">struct InvertedElem
{
std::uint64_t doc_id;
std::string word;
int weight;//权重
};
</code></pre><p>倒排拉链:</p><pre><code class="prism language-c++">typedef std::vector InvertedList;
</code></pre><p>倒排索引:</p><pre><code class="prism language-c++">std::unordered_map inverted_index;
</code></pre><p>倒排索引紧跟在正排索引之后,当网页正文文件的某一行被加入到正排索引之后,会返回一个带有文档ID的DocInfo,此时可以统计该文档的词频,根据词频计算每个词的权重。</p><pre><code class="prism language-c++">//用于权重计算
#define X 10
#define Y 1
bool BuildInvertedIndex(const DocInfo &doc)
{
//1.词频统计
struct word_cnt
{
int title_cnt;
int content_cnt;
word_cnt(): title_cnt(0),content_cnt(0){}
};
std::unordered_map word_map;
//对标题进行分词并进行统计
std::vector title_words;
ns_util::JiebaUtil::CutString(doc.title, &title_words);
for(auto it : title_words)
{
boost::to_lower(it);//将分词全部转换成小写
word_map[it].title_cnt++;
}
//对文档内容进行分词并进行统计
std::vector content_words;
ns_util::JiebaUtil::CutString(doc.content,&content_words);
for(auto it : content_words)
{
boost::to_lower(it);//将分词全部转换成小写
word_map[it].content_cnt++;
}
//进行权重计算
for(auto &word_pair : word_map)
{
InvertedElem item;
item.doc_id=doc.doc_id;
item.word=word_pair.first;
item.weight = X * word_pair.second.title_cnt + Y * word_pair.second.content_cnt;
InvertedList& inverted_list = inverted_index[word_pair.first];
inverted_list.push_back(std::move(item));
}
return true;
}
</code></pre><p>正排索引和倒排索引结合,将网页正文文件的每一行(每一个文档)进行处理,完成所有索引的建立任务。</p><p>index.hpp:</p><pre><code class="prism language-c++">#pragma once
#include 
#include 
#include 
#include 
#include 
#include 
#include "util.hpp"
#include "log.hpp"
#define X 10
#define Y 1
namespace ns_index
{
struct DocInfo
{
std::string title;//文档的标题
std::string content;//文档的主体
std::string url;//文档网页的链接
std::uint64_t doc_id; //文档的ID
};
struct InvertedElem
{
std::uint64_t doc_id;
std::string word;
int weight;//权重
};
typedef std::vector InvertedList; //倒排拉链
class Index
{
private:
Index(){}
Index(const Index&) = delete;
Index& operator=(const Index&) = delete;
static Index* instance;
static std::mutex locker;
public:
~Index(){}
public:
static Index* GetInstance()
{
if(nullptr == instance)
{
locker.lock();
if(nullptr == instance)
{
instance=new Index();
}
locker.unlock();
}
return instance;
}
//根据doc_id找出文档内容
DocInfo* GetForwardIndex(std::uint64_t doc_id)
{
if(doc_id>=forward_index.size())
{
std::cerr<<"doc_id:"<<doc_id<<" out of range"<second);
}
//根据去标签之后的文档,构建正排和倒排索引
bool BuildIndex(const std::string &input)
{
std::ifstream in(input, std::ios::in | std::ios::binary);
if(!in.is_open())
{
std::cerr<<input<<" open error"<<std::endl;
return false;
}
std::string line;
int count=0;
while(std::getline(in,line))
{
DocInfo* doc = BuildForwardIndex(line);
if(nullptr == doc)
{
std::cerr<<"build "<<line<<" error"<<std::endl;
continue;
}
BuildInvertedIndex(*doc);
count++;
if(count%100==0)
{
LOG(NORMAL,"当前已经建立的索引数量:"+std::to_string(count));
}
}
LOG(NORMAL,"当前已经建立的索引数量:"+std::to_string(count));
return true;
}
private:
DocInfo* BuildForwardIndex(const std::string &line)
{
//...
}
bool BuildInvertedIndex(const DocInfo &doc)
{
//...
}
private:
std::vector forward_index;//正排索引
std::unordered_map inverted_index;//倒排索引
};
Index* Index::instance=nullptr;
std::mutex Index::locker;
}
</code></pre><h2>搜索引擎的构成</h2><p>搜索引擎作为服务器的核心模块,完成用户给出的搜索词的搜索和排序功能。其结构如下:</p><h3><strong>初始化</strong></h3><p>在 <code>InitSearcher</code> 方法中,初始化 <code>Searcher</code> 类并加载索引数据:</p><ul><li><strong>获取索引实例</strong>:使用单例模式获取 <code>Index</code> 类的唯一实例。</li><li><strong>构建索引</strong>:调用 <code>BuildIndex</code> 方法,从指定输入文件中构建正排索引和倒排索引。</li></ul><h3><strong>查询处理</strong></h3><p><code>Search</code> 方法是模块的核心,用于处理查询请求:</p><ul><li><strong>分词</strong>:利用 <code>JiebaUtil</code> 对输入查询进行中文分词,生成关键词列表。</li><li><strong>索引查找</strong>:根据关键词在倒排索引中查找相关文档,将结果存储在 <code>tokens_map</code> 中,并累加每个文档的权重。</li><li><strong>结果排序</strong>:将查找到的文档按相关性(权重)降序排序,存储在 <code>inverted_list_all</code> 中。</li><li><strong>JSON构建</strong>:将排序后的结果转化为 JSON 格式的字符串,包含文档标题、简介和链接等信息。</li></ul><pre><code class="prism language-c++">//根据查询语句,搜索文档
void Search(std::string &query, std::string *json_string)
{
//1.对查询的语句进行分词
std::vector words;
ns_util::JiebaUtil::CutString(query,&words);
//2.根据各个分词,使用index索引进行查找
std::vector inverted_list_all;
std::unordered_map tokens_map;
//由于多个word可能映射到同一个文档,为了避免查询结果中文档重复,应将重复的文档合并成一个文档。
//(这里的合并指的是权重累加,文档内容不变。)
for(std::string word : words)
{
boost::to_lower(word);
ns_index::InvertedList *inverted_list = index->GetInvertedList(word);
if(nullptr==inverted_list)
{
continue;
}
for(auto &elem: *inverted_list)
{
auto &item = tokens_map[elem.doc_id];
item.doc_id=elem.doc_id;
//关键词对应的文档相同,则累加该文档的权重值
item.weight+=elem.weight;
item.words.push_back(elem.word);
}
}
for(const auto& elem : tokens_map)
{
inverted_list_all.push_back(std::move(elem.second));
}
//3.汇总查找结果,按照相关性进行降序排序
std::sort(inverted_list_all.begin(),inverted_list_all.end(),\
[](const InvertedListPrint &e1, const InvertedListPrint &e2){return e1.weight>e2.weight;});
//4.根据查找结果,构建json串
Json::Value root;
for(auto &item:inverted_list_all)
{
ns_index::DocInfo* doc = index->GetForwardIndex(item.doc_id);
if(nullptr==doc)
{
continue;
}
Json::Value elem;
elem["title"]=doc->title;
elem["desc"]=GetDesc(doc->content,item.words[0]);//获取关键词的相关简介
elem["url"]=doc->url;
elem["weight"]=item.weight;
root.append(elem);
}
Json::FastWriter writer;
*json_string=writer.write(root);
}
</code></pre><h3><strong>简介生成</strong></h3><p><code>GetDesc</code> 方法用于从文档内容中提取包含查询词的片段,生成简介:</p><ul><li><strong>查找关键词</strong>:在文档内容中查找查询词的位置。</li><li><strong>提取片段</strong>:从关键词位置前后一定范围内提取内容片段,作为简介。</li></ul><p>seacher.hpp:</p><pre><code class="prism language-c++">#pragma once
#include 
#include 
#include 
#include "index.hpp"
#include "util.hpp"
#include "log.hpp"
namespace ns_seacher
{
struct InvertedListPrint
{
uint64_t doc_id;
int weight;
std::vector words;
};
class Searcher
{
public:
Searcher(){}
~Searcher(){}
public:
void InitSearcher(const std::string &input)
{
//1.获取Index对象
index=ns_index::Index::GetInstance();
LOG(NORMAL,"获取单例索引成功");
//2.建立索引
index->BuildIndex(input);
LOG(NORMAL,"建立正排和倒排索引成功");
}
//根据查询语句,搜索文档
void Search(std::string &query, std::string *json_string)
{
//...
}
//获取搜索词的简介
std::string GetDesc(const std::string &content, const std::string &word)
{
//根据
auto it = std::search(content.begin(),content.end(),word.begin(),word.end(),\
[](int x,int y){return std::tolower(x)==std::tolower(y);});
if(it==content.end())
{
return "None1";
}
//正文[...]
//简介截取范围 [...["key_word"]...]
int pos = std::distance(content.begin(),it);
const int prev_step=50;
const int next_step=100;
int begin=0;
int end = content.size()-1;
if(pos-prev_step>begin)
{
begin=pos-prev_step;
}
if(pos+next_step=end)
{
return "None2";
}
return content.substr(begin,end-begin) + "...";
}
private:
ns_index::Index *index;
};
}
</code></pre><h2>前端网页</h2><p>实现目的:基本的搜索功能,包括查询输入、搜索结果显示和分页控制。</p><h3>查询输入</h3><pre><code class="prism language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>请输入关键字...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token special-attr"><span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token function">Search</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>搜索一下<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>result<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pagination<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token special-attr"><span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token function">PrevPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>上一页<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pageCounter<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>第 1 页<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token special-attr"><span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token function">NextPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>下一页<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript">
<span class="token comment">// JavaScript 代码在此定义</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span>
</code></pre><h3>搜索以及结果展示</h3><pre><code class="prism language-javascript"><span class="token keyword">let</span> currentPage <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> pageSize <span class="token operator">=</span> <span class="token number">15</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> totalPages <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> searchData <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">Search</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> query <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".container .search input"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">val</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>query <span class="token operator">==</span> <span class="token string">''</span> <span class="token operator">||</span> query <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
$<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"GET"</span><span class="token punctuation">,</span>
<span class="token literal-property property">url</span><span class="token operator">:</span> <span class="token string">"/s?word="</span> <span class="token operator">+</span> query<span class="token punctuation">,</span>
<span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
searchData <span class="token operator">=</span> data<span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>searchData <span class="token operator">==</span> <span class="token string">''</span> <span class="token operator">||</span> searchData <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
document<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"没有找到要搜索的内容"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
totalPages <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">ceil</span><span class="token punctuation">(</span>searchData<span class="token punctuation">.</span>length <span class="token operator">/</span> pageSize<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">DisplayResults</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">UpdatePagination</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">DisplayResults</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>searchData <span class="token operator">==</span> <span class="token string">''</span> <span class="token operator">||</span> searchData <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
document<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"没有找到要搜索的内容"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> result_lable <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".container .result"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
result_lable<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> startIndex <span class="token operator">=</span> <span class="token punctuation">(</span>currentPage <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">*</span> pageSize<span class="token punctuation">;</span>
<span class="token keyword">let</span> endIndex <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>startIndex <span class="token operator">+</span> pageSize<span class="token punctuation">,</span> searchData<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> startIndex<span class="token punctuation">;</span> i <span class="token operator"><</span> endIndex<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> elem <span class="token operator">=</span> searchData<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> a_label <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token literal-property property">text</span><span class="token operator">:</span> elem<span class="token punctuation">.</span>title<span class="token punctuation">,</span>
<span class="token literal-property property">href</span><span class="token operator">:</span> elem<span class="token punctuation">.</span>url<span class="token punctuation">,</span>
<span class="token literal-property property">target</span><span class="token operator">:</span> <span class="token string">"_blank"</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> p_label <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"<p>"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token literal-property property">text</span><span class="token operator">:</span> elem<span class="token punctuation">.</span>desc
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> i_label <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"<i>"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token literal-property property">text</span><span class="token operator">:</span> elem<span class="token punctuation">.</span>url
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> div_label <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token keyword">class</span><span class="token operator">:</span> <span class="token string">"item"</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
a_label<span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span>div_label<span class="token punctuation">)</span><span class="token punctuation">;</span>
p_label<span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span>div_label<span class="token punctuation">)</span><span class="token punctuation">;</span>
i_label<span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span>div_label<span class="token punctuation">)</span><span class="token punctuation">;</span>
div_label<span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span>result_lable<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h3>分页控制</h3><pre><code class="prism language-javascript"><span class="token keyword">function</span> <span class="token function">UpdatePagination</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#pageCounter"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token string">"第 "</span> <span class="token operator">+</span> currentPage <span class="token operator">+</span> <span class="token string">" 页,共 "</span> <span class="token operator">+</span> totalPages <span class="token operator">+</span> <span class="token string">" 页"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">NextPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>currentPage <span class="token operator"><</span> totalPages<span class="token punctuation">)</span> <span class="token punctuation">{</span>
currentPage<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token function">DisplayResults</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">UpdatePagination</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">PrevPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>currentPage <span class="token operator">></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
currentPage<span class="token operator">--</span><span class="token punctuation">;</span>
<span class="token function">DisplayResults</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">UpdatePagination</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><h3>CSS样式</h3><pre><code class="prism language-css">
<span class="token comment">/* 去掉网页中的所有的默认内外边距,html的盒子模型 */</span>
<span class="token selector">*</span> <span class="token punctuation">{</span>
<span class="token comment">/* 设置外边距 */</span>
<span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token comment">/* 设置内边距 */</span>
<span class="token property">padding</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 将我们的body内的内容100%和html的呈现吻合 */</span>
<span class="token selector">html,
body</span> <span class="token punctuation">{</span>
<span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 类选择器.container */</span>
<span class="token selector">.container</span> <span class="token punctuation">{</span>
<span class="token comment">/* 设置div的宽度 */</span>
<span class="token property">width</span><span class="token punctuation">:</span> 800px<span class="token punctuation">;</span>
<span class="token comment">/* 通过设置外边距达到居中对齐的目的 */</span>
<span class="token property">margin</span><span class="token punctuation">:</span> 0px auto<span class="token punctuation">;</span>
<span class="token comment">/* 设置外边距的上边距,保持元素和网页的上部距离 */</span>
<span class="token property">margin-top</span><span class="token punctuation">:</span> 15px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 复合选择器,选中container 下的 search */</span>
<span class="token selector">.container .search</span> <span class="token punctuation">{</span>
<span class="token comment">/* 宽度与父标签保持一致 */</span>
<span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
<span class="token comment">/* 高度设置为52px */</span>
<span class="token property">height</span><span class="token punctuation">:</span> 52px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 先选中input标签, 直接设置标签的属性,先要选中, input:标签选择器*/</span>
<span class="token comment">/* input在进行高度设置的时候,没有考虑边框的问题 */</span>
<span class="token selector">.container .search input</span> <span class="token punctuation">{</span>
<span class="token comment">/* 设置left浮动 */</span>
<span class="token property">float</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span>
<span class="token property">width</span><span class="token punctuation">:</span> 600px<span class="token punctuation">;</span>
<span class="token property">height</span><span class="token punctuation">:</span> 50px<span class="token punctuation">;</span>
<span class="token comment">/* 设置边框属性:边框的宽度,样式,颜色 */</span>
<span class="token property">border</span><span class="token punctuation">:</span> 1px solid black<span class="token punctuation">;</span>
<span class="token comment">/* 去掉input输入框的有边框 */</span>
<span class="token property">border-right</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token comment">/* 设置内边距,默认文字不要和左侧边框紧挨着 */</span>
<span class="token property">padding-left</span><span class="token punctuation">:</span> 10px<span class="token punctuation">;</span>
<span class="token comment">/* 设置input内部的字体的颜色和样式 */</span>
<span class="token property">color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>
<span class="token property">font-size</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 先选中button标签, 直接设置标签的属性,先要选中, button:标签选择器*/</span>
<span class="token selector">.container .search button</span> <span class="token punctuation">{</span>
<span class="token comment">/* 设置left浮动 */</span>
<span class="token property">float</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span>
<span class="token property">width</span><span class="token punctuation">:</span> 150px<span class="token punctuation">;</span>
<span class="token property">height</span><span class="token punctuation">:</span> 52px<span class="token punctuation">;</span>
<span class="token comment">/* 设置button的背景颜色,#4e6ef2 */</span>
<span class="token property">background-color</span><span class="token punctuation">:</span> #4e6ef2<span class="token punctuation">;</span>
<span class="token comment">/* 设置button中的字体颜色 */</span>
<span class="token property">color</span><span class="token punctuation">:</span> #FFF<span class="token punctuation">;</span>
<span class="token comment">/* 设置字体的大小 */</span>
<span class="token property">font-size</span><span class="token punctuation">:</span> 19px<span class="token punctuation">;</span>
<span class="token property">font-family</span><span class="token punctuation">:</span>Georgia<span class="token punctuation">,</span> <span class="token string">'Times New Roman'</span><span class="token punctuation">,</span> Times<span class="token punctuation">,</span> serif<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.container .result .item</span><span class="token punctuation">{</span>
<span class="token property">margin-top</span><span class="token punctuation">:</span> 15px<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.container .result .item a</span><span class="token punctuation">{</span>
<span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span>
<span class="token property">text-decoration</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token property">font-size</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span>
<span class="token property">color</span><span class="token punctuation">:</span> #4e6ef2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.container .result .item a:hover</span><span class="token punctuation">{</span>
<span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.container .result .item p</span><span class="token punctuation">{</span>
<span class="token property">margin-top</span><span class="token punctuation">:</span> 5px<span class="token punctuation">;</span>
<span class="token property">font-size</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>
<span class="token property">font-family</span><span class="token punctuation">:</span><span class="token string">'Lucida Sans'</span><span class="token punctuation">,</span> <span class="token string">'Lucida Sans Regular'</span><span class="token punctuation">,</span> <span class="token string">'Lucida Grande'</span><span class="token punctuation">,</span> <span class="token string">'Lucida Sans Unicode'</span><span class="token punctuation">,</span> Geneva<span class="token punctuation">,</span> Verdana<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.container .result .item i</span><span class="token punctuation">{</span>
<span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span>
<span class="token property">font-style</span><span class="token punctuation">:</span> normal<span class="token punctuation">;</span>
<span class="token property">color</span><span class="token punctuation">:</span> green<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.pagination</span> <span class="token punctuation">{</span>
<span class="token property">margin-top</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span>
<span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.pagination button</span> <span class="token punctuation">{</span>
<span class="token property">margin</span><span class="token punctuation">:</span> 0 5px<span class="token punctuation">;</span>
<span class="token property">padding</span><span class="token punctuation">:</span> 5px 10px<span class="token punctuation">;</span>
<span class="token property">background-color</span><span class="token punctuation">:</span> #4e6ef2<span class="token punctuation">;</span>
<span class="token property">color</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span>
<span class="token property">border</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token property">border-radius</span><span class="token punctuation">:</span> 5px<span class="token punctuation">;</span>
<span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">#pageCounter</span> <span class="token punctuation">{</span>
<span class="token property">font-size</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>
<span class="token property">font-weight</span><span class="token punctuation">:</span> bold<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h2>HTTP服务</h2><p>用于和前端交互的模块,使得用户可以在浏览器上访问服务。</p><h3>工作流程概述</h3><ol><li><strong>启动阶段</strong>:<ul><li>初始化搜索器,建立索引。</li><li>配置HTTP服务器的根目录。</li><li>定义处理搜索请求的逻辑。</li></ul></li><li><strong>运行阶段</strong>:<ul><li>服务器启动并监听端口8081。</li><li>当客户端发送搜索请求时,服务器检查请求参数,处理搜索请求,生成JSON格式的结果,并返回给客户端。</li><li>记录用户的搜索关键词和相关日志信息。</li></ul></li></ol><p>http_server.cc:</p><pre><code class="prism language-c++">#include 
#include "seacher.hpp"
#include "cpp-httplib/httplib.h"
#include "log.hpp"
const std::string root_path="./wwwroot";//网页资源
const std::string input="data/raw_html/raw.txt";
int main()
{
ns_seacher::Searcher search;
search.InitSearcher(input);
httplib::Server svr;
svr.set_base_dir(root_path.c_str());
svr.Get("/s",[&search](const httplib::Request& req, httplib::Response& resp){
if(!req.has_param("word"))
{
resp.set_content("必须要有搜索关键字!","text/plain;charset=utf-8");
return;
}
std::string word = req.get_param_value("word");
std::string json_string;
LOG(NORMAL,"用户在搜索:"+word);
search.Search(word,&json_string);
resp.set_content(json_string,"application/json");
});
LOG(NORMAL,"服务器启动成功...");
svr.listen("0.0.0.0",8081);
return 0;
}
</code></pre><h3>部署服务器</h3><p>启动http_server为后台进程,并开启日志。</p><pre><code>./http_server > log/log.txt 2>&1 &
</code></pre><p>查询进程状态</p><pre><code>ps -ef | awk 'NR==1 || /http_server/' | grep -v awk
</code></pre><p><img title="boost搜索引擎插图" alt="boost搜索引擎插图"  src="/images/2024/0609/12d7c88835660e0b2b99a8000a9e1fda.png" /></p><p>部署之后的日志</p><pre><code>[2024-06-09 11:19:05][NORMAL][获取单例索引成功][seacher.hpp : 26]
[2024-06-09 11:19:10][NORMAL][当前已经建立的索引数量:100][index.hpp : 266]
[2024-06-09 11:21:57][NORMAL][当前已经建立的索引数量:200][index.hpp : 266]
[2024-06-09 11:22:22][NORMAL][当前已经建立的索引数量:300][index.hpp : 266]
[2024-06-09 11:24:34][NORMAL][当前已经建立的索引数量:400][index.hpp : 266]
[2024-06-09 11:24:35][NORMAL][当前已经建立的索引数量:500][index.hpp : 266]
[2024-06-09 11:24:35][NORMAL][当前已经建立的索引数量:600][index.hpp : 266]
...
[2024-06-09 11:27:03][NORMAL][当前已经建立的索引数量:8400][index.hpp : 266]
[2024-06-09 11:28:45][NORMAL][当前已经建立的索引数量:8500][index.hpp : 266]
[2024-06-09 11:30:21][NORMAL][当前已经建立的索引数量:8592][index.hpp : 270]
[2024-06-09 11:30:21][NORMAL][建立正排和倒排索引成功][seacher.hpp : 29]
[2024-06-09 11:30:21][NORMAL][服务器启动成功...][http_server.cc : 26]
</code></pre><h2>项目展示</h2><h3>启动页面</h3><p><img title="boost搜索引擎插图(1)" alt="boost搜索引擎插图(1)"  src="/images/2024/0609/9ea92728202e3d08b9e63ab58636d4f7.png" /></p><h3>搜索结果页面</h3><p><img title="boost搜索引擎插图(2)" alt="boost搜索引擎插图(2)"  src="/images/2024/0609/3f3d1e7d2645dc00f67c657211508bb5.png" /></p><p>日志</p><pre><code>[2024-06-09 11:53:23][NORMAL][用户在搜索:linux system][http_server.cc : 22]
</code></pre><p>点击标题访问boost网站资源</p><p>例如:点击<code>Revision History</code>,则跳转到如下网页。</p><p><img title="boost搜索引擎插图(3)" alt="boost搜索引擎插图(3)"  src="/images/2024/0609/5c7312a8024d37915a62c16b1796b1eb.png" /><br /> (项目gitee仓库)</p></article><div id="pay-single-box"></div><div class="entry-tags"> <a href="http://www.xu0.com/tag/sou-suo-yin-qing" rel="tag"> 搜索引擎 </a></div><div class="article-copyright">本站无任何商业行为<br/><a href="http://www.xu0.com">个人在线分享</a> » <a href="http://www.xu0.com/39363.html">boost搜索引擎</a></div><div class="article-footer"><div class="author-box"><div class="author-image"> <img alt='admin' data-src='http://xu0.com/wp-content/uploads/avatar/avatar-1.png' class='lazyload avatar avatar-140 photo gravatar' height='140' width='140' /></div><div class="author-info"><h4 class="author-name"> <a                            href="http://www.xu0.com/author/admin">admin</a> <span class="label label-warning"><i class="fa fa-diamond"></i> 钻石</span></h4></div></div><div class="xshare"> <span class="xshare-title">分享到:</span> <a href="" etap="share" data-share="qq" class="share-qq"><i class="fa fa-qq"></i></a> <a href="" etap="share" data-share="weibo" class="share-weibo"><i class="fa fa-weibo"></i></a></div></div></div></div></div></main><div class="entry-navigation"><nav class="article-nav"> <span class="article-nav-prev">上一篇<br><a href="http://www.xu0.com/39362.html" rel="prev">在Java中使用SeleniumAPI,超详细</a></span> <span class="article-nav-next">下一篇<br><a href="http://www.xu0.com/39367.html" rel="next">学习分享-声明式的 HTTP 客户端OpenFeign</a></span></nav></div></div><div class="coments" style="margin-top:20px;"></div></div><div class="sidebar-column col-lg-3"><aside class="widget-area"><div id="search-2" class="widget widget_search"><form method="get" class="search-form inline" action="http://www.xu0.com/"> <input type="search" class="search-field inline-field" placeholder="输入关键词,回车..." autocomplete="off" value="" name="s" required="required"> <button type="submit" class="search-submit"><i class="mdi mdi-magnify"></i></button></form></div><div id="tag_cloud-2" class="widget widget_tag_cloud"><h5 class="widget-title">标签</h5><div class="tagcloud"><a href="http://www.xu0.com/tag/android" class="tag-cloud-link tag-link-2417 tag-link-position-1" style="font-size: 9.410071942446pt;" aria-label="android (1,133个项目)">android</a> <a href="http://www.xu0.com/tag/c" class="tag-cloud-link tag-link-2388 tag-link-position-2" style="font-size: 14.244604316547pt;" aria-label="C++ (3,406个项目)">C++</a> <a href="http://www.xu0.com/tag/css" class="tag-cloud-link tag-link-2368 tag-link-position-3" style="font-size: 11.625899280576pt;" aria-label="css (1,876个项目)">css</a> <a href="http://www.xu0.com/tag/c-yu-yan" class="tag-cloud-link tag-link-2360 tag-link-position-4" style="font-size: 9.8129496402878pt;" aria-label="c语言 (1,241个项目)">c语言</a> <a href="http://www.xu0.com/tag/docker" class="tag-cloud-link tag-link-2464 tag-link-position-5" style="font-size: 10.115107913669pt;" aria-label="docker (1,314个项目)">docker</a> <a href="http://www.xu0.com/tag/html" class="tag-cloud-link tag-link-2375 tag-link-position-6" style="font-size: 12.330935251799pt;" aria-label="html (2,187个项目)">html</a> <a href="http://www.xu0.com/tag/ava" class="tag-cloud-link tag-link-267 tag-link-position-7" style="font-size: 18.172661870504pt;" aria-label="Java (8,382个项目)">Java</a> <a href="http://www.xu0.com/tag/javascript" class="tag-cloud-link tag-link-2361 tag-link-position-8" style="font-size: 18.273381294964pt;" aria-label="javascript (8,468个项目)">javascript</a> <a href="http://www.xu0.com/tag/leetcode" class="tag-cloud-link tag-link-2864 tag-link-position-9" style="font-size: 8.705035971223pt;" aria-label="leetcode (960个项目)">leetcode</a> <a href="http://www.xu0.com/tag/linux" class="tag-cloud-link tag-link-2465 tag-link-position-10" style="font-size: 14.244604316547pt;" aria-label="linux (3,402个项目)">linux</a> <a href="http://www.xu0.com/tag/mysql" class="tag-cloud-link tag-link-2485 tag-link-position-11" style="font-size: 10.215827338129pt;" aria-label="mysql (1,361个项目)">mysql</a> <a href="http://www.xu0.com/tag/python" class="tag-cloud-link tag-link-2362 tag-link-position-12" style="font-size: 16.561151079137pt;" aria-label="python (5,736个项目)">python</a> <a href="http://www.xu0.com/tag/spring" class="tag-cloud-link tag-link-2398 tag-link-position-13" style="font-size: 9.7122302158273pt;" aria-label="spring (1,200个项目)">spring</a> <a href="http://www.xu0.com/tag/springboot" class="tag-cloud-link tag-link-2400 tag-link-position-14" style="font-size: 12.532374100719pt;" aria-label="springboot (2,266个项目)">springboot</a> <a href="http://www.xu0.com/tag/uni-app" class="tag-cloud-link tag-link-2446 tag-link-position-15" style="font-size: 9.3093525179856pt;" aria-label="uni-app (1,088个项目)">uni-app</a> <a href="http://www.xu0.com/tag/vue" class="tag-cloud-link tag-link-2411 tag-link-position-16" style="font-size: 8.705035971223pt;" aria-label="vue (944个项目)">vue</a> <a href="http://www.xu0.com/tag/vuejs" class="tag-cloud-link tag-link-2371 tag-link-position-17" style="font-size: 16.561151079137pt;" aria-label="vue.js (5,713个项目)">vue.js</a> <a href="http://www.xu0.com/tag/web-an-quan" class="tag-cloud-link tag-link-2504 tag-link-position-18" style="font-size: 8.9064748201439pt;" aria-label="web安全 (1,006个项目)">web安全</a> <a href="http://www.xu0.com/tag/windows" class="tag-cloud-link tag-link-2418 tag-link-position-19" style="font-size: 8pt;" aria-label="windows (819个项目)">windows</a> <a href="http://www.xu0.com/tag/ren-gong-zhi-neng" class="tag-cloud-link tag-link-15 tag-link-position-20" style="font-size: 16.661870503597pt;" aria-label="人工智能 (5,918个项目)">人工智能</a> <a href="http://www.xu0.com/tag/qian-duan" class="tag-cloud-link tag-link-2366 tag-link-position-21" style="font-size: 22pt;" aria-label="前端 (19,994个项目)">前端</a> <a href="http://www.xu0.com/tag/qian-duan-kuang-jia" class="tag-cloud-link tag-link-2397 tag-link-position-22" style="font-size: 9.0071942446043pt;" aria-label="前端框架 (1,031个项目)">前端框架</a> <a href="http://www.xu0.com/tag/dan-pian-ji" class="tag-cloud-link tag-link-2943 tag-link-position-23" style="font-size: 8.2014388489209pt;" aria-label="单片机 (856个项目)">单片机</a> <a href="http://www.xu0.com/tag/hou-duan" class="tag-cloud-link tag-link-2401 tag-link-position-24" style="font-size: 13.035971223022pt;" aria-label="后端 (2,565个项目)">后端</a> <a href="http://www.xu0.com/tag/da-shu-ju" class="tag-cloud-link tag-link-2450 tag-link-position-25" style="font-size: 12.028776978417pt;" aria-label="大数据 (2,037个项目)">大数据</a> <a href="http://www.xu0.com/tag/xue-xi" class="tag-cloud-link tag-link-2435 tag-link-position-26" style="font-size: 13.338129496403pt;" aria-label="学习 (2,762个项目)">学习</a> <a href="http://www.xu0.com/tag/an-quan" class="tag-cloud-link tag-link-2568 tag-link-position-27" style="font-size: 11.021582733813pt;" aria-label="安全 (1,615个项目)">安全</a> <a href="http://www.xu0.com/tag/rong-qi" class="tag-cloud-link tag-link-2463 tag-link-position-28" style="font-size: 9.1079136690647pt;" aria-label="容器 (1,045个项目)">容器</a> <a href="http://www.xu0.com/tag/xiao-cheng-xu" class="tag-cloud-link tag-link-2459 tag-link-position-29" style="font-size: 9.6115107913669pt;" aria-label="小程序 (1,171个项目)">小程序</a> <a href="http://www.xu0.com/tag/qian-ru-shi-ying-jian" class="tag-cloud-link tag-link-2944 tag-link-position-30" style="font-size: 8.3021582733813pt;" aria-label="嵌入式硬件 (874个项目)">嵌入式硬件</a> <a href="http://www.xu0.com/tag/kai-fa-yu-yan" class="tag-cloud-link tag-link-2372 tag-link-position-31" style="font-size: 17.971223021583pt;" aria-label="开发语言 (7,904个项目)">开发语言</a> <a href="http://www.xu0.com/tag/wei-xin-xiao-cheng-xu" class="tag-cloud-link tag-link-2424 tag-link-position-32" style="font-size: 8.6043165467626pt;" aria-label="微信小程序 (934个项目)">微信小程序</a> <a href="http://www.xu0.com/tag/%e6%95%b0%e6%8d%ae%e5%ba%93" class="tag-cloud-link tag-link-304 tag-link-position-33" style="font-size: 14.748201438849pt;" aria-label="数据库 (3,785个项目)">数据库</a> <a href="http://www.xu0.com/tag/shu-ju-jie-gou" class="tag-cloud-link tag-link-2460 tag-link-position-34" style="font-size: 10.517985611511pt;" aria-label="数据结构 (1,458个项目)">数据结构</a> <a href="http://www.xu0.com/tag/fu-wu-qi" class="tag-cloud-link tag-link-2436 tag-link-position-35" style="font-size: 13.841726618705pt;" aria-label="服务器 (3,066个项目)">服务器</a> <a href="http://www.xu0.com/tag/ji-qi-xue-xi" class="tag-cloud-link tag-link-2603 tag-link-position-36" style="font-size: 9.7122302158273pt;" aria-label="机器学习 (1,202个项目)">机器学习</a> <a href="http://www.xu0.com/tag/shen-du-xue-xi" class="tag-cloud-link tag-link-2469 tag-link-position-37" style="font-size: 10.820143884892pt;" aria-label="深度学习 (1,559个项目)">深度学习</a> <a href="http://www.xu0.com/tag/bi-ji" class="tag-cloud-link tag-link-2587 tag-link-position-38" style="font-size: 11.827338129496pt;" aria-label="笔记 (1,960个项目)">笔记</a> <a href="http://www.xu0.com/tag/suan-fa" class="tag-cloud-link tag-link-2386 tag-link-position-39" style="font-size: 14.446043165468pt;" aria-label="算法 (3,536个项目)">算法</a> <a href="http://www.xu0.com/tag/wang-luo" class="tag-cloud-link tag-link-853 tag-link-position-40" style="font-size: 13.035971223022pt;" aria-label="网络 (2,577个项目)">网络</a> <a href="http://www.xu0.com/tag/wang-luo-xie-yi" class="tag-cloud-link tag-link-2437 tag-link-position-41" style="font-size: 8.8057553956835pt;" aria-label="网络协议 (971个项目)">网络协议</a> <a href="http://www.xu0.com/tag/wang-luo-an-quan" class="tag-cloud-link tag-link-2505 tag-link-position-42" style="font-size: 8pt;" aria-label="网络安全 (814个项目)">网络安全</a> <a href="http://www.xu0.com/tag/yun-wei" class="tag-cloud-link tag-link-2477 tag-link-position-43" style="font-size: 14.345323741007pt;" aria-label="运维 (3,493个项目)">运维</a> <a href="http://www.xu0.com/tag/mian-shi" class="tag-cloud-link tag-link-2445 tag-link-position-44" style="font-size: 9.0071942446043pt;" aria-label="面试 (1,027个项目)">面试</a> <a href="http://www.xu0.com/tag/yin-shi-pin" class="tag-cloud-link tag-link-2438 tag-link-position-45" style="font-size: 8.8057553956835pt;" aria-label="音视频 (969个项目)">音视频</a></div></div><div id="calendar-2" class="widget widget_calendar"><div id="calendar_wrap" class="calendar_wrap"><table id="wp-calendar" class="wp-calendar-table"><caption>2024年七月</caption><thead><tr><th scope="col" title="星期一">一</th><th scope="col" title="星期二">二</th><th scope="col" title="星期三">三</th><th scope="col" title="星期四">四</th><th scope="col" title="星期五">五</th><th scope="col" title="星期六">六</th><th scope="col" title="星期日">日</th></tr></thead><tbody><tr><td colspan="6" class="pad"> </td><td>1</td></tr><tr><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td></tr><tr><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td><td>15</td></tr><tr><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td><td>22</td></tr><tr><td>23</td><td>24</td><td>25</td><td>26</td><td>27</td><td>28</td><td>29</td></tr><tr><td>30</td><td class="pad" colspan="6"> </td></tr></tbody></table><nav aria-label="上个月及下个月" class="wp-calendar-nav"> <span class="wp-calendar-nav-prev"><a href="http://www.xu0.com/date/2024/06">« 6月</a></span> <span class="pad"> </span> <span class="wp-calendar-nav-next"> </span></nav></div></div></aside></div></div><div class="related-posts-grid"><h4 class="u-border-title">相关推荐</h4><div class="row"><div class="col-6 col-sm-3 col-md-3 mt-10 mb-10"><article class="post"><div class="entry-media"><div class="placeholder" style="padding-bottom: 66.666666666667%;"> <a  href="http://www.xu0.com/91000.html"> <img class="lazyload" data-src="http://www.xu0.com/wp-content/uploads/2024/06/1718452874-5b62f6976716cda.png" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="CDN绕过技术"> </a></div></div><div class="entry-wrapper"><header class="entry-header"><h4 class="entry-title"><a href="http://www.xu0.com/91000.html" title="CDN绕过技术" rel="bookmark">CDN绕过技术</a></h4></header></div></article></div><div class="col-6 col-sm-3 col-md-3 mt-10 mb-10"><article class="post"><div class="entry-media"><div class="placeholder" style="padding-bottom: 66.666666666667%;"> <a  href="http://www.xu0.com/59288.html"> <img class="lazyload" data-src="/images/2024/0610/4973d4144bbbe9b362cbf0d1514d2e81.jpeg" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Elasticsearch index 设置 false,为什么还可以被检索到?"> </a></div></div><div class="entry-wrapper"><header class="entry-header"><h4 class="entry-title"><a href="http://www.xu0.com/59288.html" title="Elasticsearch index 设置 false,为什么还可以被检索到?" rel="bookmark">Elasticsearch index 设置 false,为什么还可以被检索到?</a></h4></header></div></article></div><div class="col-6 col-sm-3 col-md-3 mt-10 mb-10"><article class="post"><div class="entry-media"><div class="placeholder" style="padding-bottom: 66.666666666667%;"> <a  href="http://www.xu0.com/25692.html"> <img class="lazyload" data-src="/images/2024/0608/c43c515df959f7eccda3a09e68d17902.gif" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="谷歌AI搜索变革,中国引擎能跟上步伐?"> </a></div></div><div class="entry-wrapper"><header class="entry-header"><h4 class="entry-title"><a href="http://www.xu0.com/25692.html" title="谷歌AI搜索变革,中国引擎能跟上步伐?" rel="bookmark">谷歌AI搜索变革,中国引擎能跟上步伐?</a></h4></header></div></article></div><div class="col-6 col-sm-3 col-md-3 mt-10 mb-10"><article class="post"><div class="entry-media"><div class="placeholder" style="padding-bottom: 66.666666666667%;"> <a  href="http://www.xu0.com/16432.html"> <img class="lazyload" data-src="/images/2024/0608/c43c515df959f7eccda3a09e68d17902.gif" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="谷歌AI搜索变革,中国引擎能跟上步伐?"> </a></div></div><div class="entry-wrapper"><header class="entry-header"><h4 class="entry-title"><a href="http://www.xu0.com/16432.html" title="谷歌AI搜索变革,中国引擎能跟上步伐?" rel="bookmark">谷歌AI搜索变革,中国引擎能跟上步伐?</a></h4></header></div></article></div></div></div> E--></div><footer class="site-footer"><div class="container"><div class="footer-widget"><div class="row"><div class="col-xs-12 col-sm-6 col-md-3 widget--about"><div class="widget--content"><div class="footer--logo mb-20"> <img class="tap-logo" src="http://www.xu0.com/wp-content/uploads/2024/06/1718412997-7db64bdd170b2cd.png"
data-dark="http://www.xu0.com/wp-content/uploads/2024/06/1718412997-7db64bdd170b2cd.png"
alt="个人在线分享"></div><p class="mb-10">本站无任何商业行为</p></div></div><div class="col-xs-12 col-sm-3 col-md-2 col-md-offset-1 widget--links"><div class="widget--title"><h5>本站导航</h5></div><div class="widget--content"><ul class="list-unstyled mb-0"></ul></div></div><div class="col-xs-12 col-sm-3 col-md-2 widget--links"><div class="widget--title"><h5>友情链接</h5></div><div class="widget--content"><ul class="list-unstyled mb-0"></ul></div></div><div class="col-xs-12 col-sm-12 col-md-4 widget--newsletter"><div class="widget--title"><h5>快速搜索</h5></div><div class="widget--content"><form class="newsletter--form mb-30" action="http://www.xu0.com/" method="get"> <input type="text" class="form-control" name="s" placeholder="关键词"> <button type="submit"><i class="fa fa-arrow-right"></i></button></form><h6>本站由<a href="http://ritheme.com/" target="_blank" rel="noreferrer nofollow">RiPro主题</a>强力驱动</h6><h6><div class="payment"></div></h6></div></div></div></div><div class="site-info"> © 2018 Theme by - <a href="http://ritheme.com/" target="_blank" rel="noreferrer nofollow">本站无任何商业行为</a> & WordPress Theme. All rights reserved <a href="https://beian.miit.gov.cn" target="_blank" class="text">蒙ICP备2023002302号-2 <br></a><div class="footer-shouquan">「虚灵个人在线分享」 XU0.COM 提供免费学习资料分享,本站资料全部由网上搜集,仅供学习使用, 不得用来做违法违纪,如有侵权请联系,立即删除</div></div></div></footer><div class="dimmer"></div><div class="off-canvas"><div class="canvas-close"><i class="mdi mdi-close"></i></div><div class="logo-wrapper"> <a href="http://www.xu0.com/"> <img class="logo regular" src="http://www.xu0.com/wp-content/uploads/2024/06/1717773004-dc1d71bbb5c4d2a.png" alt="个人在线分享"> </a></div><div class="mobile-menu hidden-lg hidden-xl"></div><aside class="widget-area"></aside></div> <script defer src="data:text/javascript;base64,DQogICAgICAgIGNvbnNvbGUubG9nKCJcbiAlYyBSaVByby3lrZDkuLvpopggVjguMSAlYyBodHRwczovL3p5Zng4LmNuIFxuXG4iLCAiY29sb3I6ICNmYWRmYTM7IGJhY2tncm91bmQ6ICMwMzAzMDc7IHBhZGRpbmc6NXB4IDA7IiwgImJhY2tncm91bmQ6ICNmYWRmYTM7IHBhZGRpbmc6NXB4IDA7Iik7DQogICAgICAgIGNvbnNvbGUubG9nKCJTUUwg6K+35rGC5pWw77yaOTQiKTsNCiAgICAgICAgY29uc29sZS5sb2coIumhtemdoueUn+aIkOiAl+aXtu+8miA0Mi4wNTk1NiIpOw0KICAgIA=="></script> <script defer src="data:text/javascript;base64,alF1ZXJ5KGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigkKXskKCcuY3QgaDMgc3BhbicpLmNsaWNrKGZ1bmN0aW9uKCl7JCh0aGlzKS5hZGRDbGFzcygic2VsZWN0ZWQiKS5zaWJsaW5ncygpLnJlbW92ZUNsYXNzKCk7JCgnLmN0ID4gdWwnKS5lcSgkKHRoaXMpLmluZGV4KCkpLmFkZENsYXNzKCdzaG93Jyk7JCgnLmN0ID4gdWwnKS5lcSgkKHRoaXMpLmluZGV4KCkpLnNpYmxpbmdzKCkucmVtb3ZlQ2xhc3MoJ3Nob3cnKTt9KTskKCJwcmUgPiBjb2RlIikuYWRkQ2xhc3MoImxhbmd1YWdlLXBocCIpO30pO2pRdWVyeSgiLmhlYWRlci1kcm9wZG93biIpLmhvdmVyKGZ1bmN0aW9uKCl7alF1ZXJ5KHRoaXMpLmFkZENsYXNzKCdhY3RpdmUnKTt9LGZ1bmN0aW9uKCl7alF1ZXJ5KHRoaXMpLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTt9KTskKCcuaC1zY3JlZW4gbGknKS5jbGljayhmdW5jdGlvbigpeyQodGhpcykuYWRkQ2xhc3MoIm9uIikuc2libGluZ3MoKS5yZW1vdmVDbGFzcygpOyQoJy5jdCA+IHVsJykuZXEoJCh0aGlzKS5pbmRleCgpKS5hZGRDbGFzcygnc2hvdycpOyQoJy5jdCA+IHVsJykuZXEoJCh0aGlzKS5pbmRleCgpKS5zaWJsaW5ncygpLnJlbW92ZUNsYXNzKCdzaG93Jyk7fSk7JCgiLmgtc291cCBsaSBpIikuY2xpY2soZnVuY3Rpb24oKXt2YXIgc291cEJ0bj0kKHRoaXMpLnBhcmVudCgpOyQoIi5oLXNvdXAgbGkiKS5yZW1vdmVDbGFzcygib3BlbiIpO3NvdXBCdG4uYWRkQ2xhc3MoIm9wZW4iKTt9KTs="></script> <script defer src="data:text/javascript;base64,JChmdW5jdGlvbigpe3ZhciBuYXZIZWlnaHQ9JCgiI25hdkhlaWdodCIpLm9mZnNldCgpLnRvcDt2YXIgbmF2Rml4PSQoIiNuYXZIZWlnaHQiKTtpZihuYXZIZWlnaHQ+MzYpe25hdkZpeC5hZGRDbGFzcygibmF2Rml4Iik7fQp3aW5kb3cub25zY3JvbGw9ZnVuY3Rpb24oKXtpZigkKHRoaXMpLnNjcm9sbFRvcCgpPm5hdkhlaWdodHx8JCh0aGlzKS5zY3JvbGxUb3AoKT4zNyl7bmF2Rml4LmFkZENsYXNzKCJuYXZGaXgiKTt9ZWxzZXtuYXZGaXgucmVtb3ZlQ2xhc3MoIm5hdkZpeCIpO319fSkKJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXt9KQp2YXIgbmR0PSQoIiNoZWxwIGR0Iik7dmFyIG5kZD0kKCIjaGVscCBkZCIpO25kZC5lcSgwKS5zaG93KCk7bmR0LmNsaWNrKGZ1bmN0aW9uKCl7bmRkLmhpZGUoKTskKHRoaXMpLm5leHQoKS5zaG93KCk7fSk7"></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_27154160b5352fe140fcf82df293b2c3.js?ver=2.0'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_f4168d76f155c6b079459b12937ec426.js?ver=8.1'></script> <script defer src="data:text/javascript;base64,Ci8qIDwhW0NEQVRBWyAqLwp2YXIgY2Fvemh1dGkgPSB7InNpdGVfbmFtZSI6Ilx1NGUyYVx1NGViYVx1NTcyOFx1N2ViZlx1NTIwNlx1NGVhYiIsImhvbWVfdXJsIjoiaHR0cDpcL1wvd3d3Lnh1MC5jb20iLCJhamF4dXJsIjoiaHR0cDpcL1wvd3d3Lnh1MC5jb21cL3dwLWFkbWluXC9hZG1pbi1hamF4LnBocCIsImlzX3Npbmd1bGFyIjoiMSIsInRlbmNlbnRfY2FwdGNoYSI6eyJpcyI6IiIsImFwcGlkIjoiIn0sImluZmluaXRlX2xvYWQiOiJcdTUyYTBcdThmN2RcdTY2ZjRcdTU5MWEiLCJpbmZpbml0ZV9sb2FkaW5nIjoiPGkgY2xhc3M9XCJmYSBmYS1zcGlubmVyIGZhLXNwaW5cIj48XC9pPiBcdTUyYTBcdThmN2RcdTRlMmQuLi4iLCJzaXRlX25vdGljZSI6eyJpcyI6IjAiLCJjb2xvciI6InJnYigzMywgMTUwLCAyNDMpIiwiaHRtbCI6IjxkaXYgY2xhc3M9XCJub3RpZnktY29udGVudFwiPjxoMz5SaVByb1x1NjcwMFx1NjViMFx1NzI0OFx1NjcyY1x1NjZmNFx1NjViMFx1NjVlNVx1NWZkNzxcL2gzPjxkaXY+XHU4ZmQ5XHU2NjJmXHU0ZTAwXHU2NzYxXHU3ZjUxXHU3YWQ5XHU1MTZjXHU1NDRhXHVmZjBjXHU1M2VmXHU1NzI4XHU1NDBlXHU1M2YwXHU1ZjAwXHU1NDJmXHU2MjE2XHU1MTczXHU5NWVkXHVmZjBjXHU1M2VmXHU4MWVhXHU1YjlhXHU0ZTQ5XHU4MGNjXHU2NjZmXHU5ODljXHU4MjcyXHVmZjBjXHU2ODA3XHU5ODk4XHVmZjBjXHU1MTg1XHU1YmI5XHVmZjBjXHU3NTI4XHU2MjM3XHU5OTk2XHU2YjIxXHU2MjUzXHU1ZjAwXHU1MTczXHU5NWVkXHU1NDBlXHU0ZTBkXHU1MThkXHU5MWNkXHU1OTBkXHU1ZjM5XHU1MWZhXHVmZjBjXHU2YjY0XHU1OTA0XHU1M2VmXHU0ZjdmXHU3NTI4aHRtbFx1NjgwN1x1N2I3ZS4uLjxcL2Rpdj48XC9kaXY+In0sInBheV90eXBlX2h0bWwiOnsiaHRtbCI6IjxkaXYgY2xhc3M9XCJwYXktYnV0dG9uLWJveFwiPjxcL2Rpdj48cCBzdHlsZT1cImZvbnQtc2l6ZTogMTNweDsgcGFkZGluZzogMDsgbWFyZ2luOiAwO1wiPlx1NTE0ZFx1OGQzOVx1NjIxNlx1OTRiYlx1NzdmM1x1NTE0ZFx1OGQzOVx1OGQ0NFx1NmU5MFx1NGVjNVx1OTY1MFx1NGY1OVx1OTg5ZFx1NjUyZlx1NGVkODxcL3A+IiwiYWxpcGF5IjowLCJ3ZWl4aW5wYXkiOjB9fTsKLyogXV0+ICovCg=="></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_3d63ae9fc20c9541c081782157cba6ee.js?ver=8.1'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/themes/ripro/assets/js/plugins/jquery.fancybox.min.js?ver=8.1'></script> <script defer src="data:text/javascript;base64,Ci8qIDwhW0NEQVRBWyAqLwp2YXIgc29jaWFsUm9ja2V0ID0geyJhamF4X3VybCI6Imh0dHA6XC9cL3d3dy54dTAuY29tXC93cC1hZG1pblwvYWRtaW4tYWpheC5waHAiLCJ3aGVyZV93ZV9hdCI6eyJpZCI6MzkzNjMsInR5cGUiOiJwb3N0IiwidXJsIjoiaHR0cDpcL1wvd3d3Lnh1MC5jb206ODFcLzM5MzYzLmh0bWwiLCJzZXR0aW5nc19rZXkiOiJwb3N0X3R5cGVfcG9zdCJ9fTsKLyogXV0+ICovCg=="></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_1d5d2ad4f5dbdf913ba6de4401f4735d.js?ver=1.3.4'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_da7438dbb3b8b182b57a5e1060df6f34.js?ver=8.1'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/themes/ripro-child/assets/js/pace.min.js?ver=8.1'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_da612dba276a3e4d6ce92172f36c2e3b.js?ver=8.1'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/themes/ripro-child/assets/js/swiper.min.js?ver=8.1'></script> <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_a286291139f4b6620b3a05c35bfc300c.js'></script>    <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_6223ec2de1bab9aaa9718f10b8bdd3bf.js'></script>  <script defer type='text/javascript' src='http://www.xu0.com/wp-content/cache/autoptimize/js/autoptimize_single_348a660b84948fec7cb3af646936d009.js'></script> </body></html><!-- WP Fastest Cache file was created in 43.003288030624 seconds, on 31-07-24 17:29:02 -->