Browser Project
Published: 2023-12-20 15:28:14

- [一、系统需求](#一系统需求)
  - [1.1 需求分析](#11-需求分析)
  - [1.2消息格式](#12消息格式)
  - [1.3 详细定义](#13-详细定义)
  - [1.4 模块划分](#14-模块划分)
    - [1.4.1 模块一 关键字推荐服务部分](#141-模块一-关键字推荐服务部分)
      - [1.4.1.1 离线部分](#1411-离线部分)
      - [1.4.1.2 在线部分](#1412-在线部分)
    - [1.4.2 模块二 网页查询部分](#142-模块二-网页查询部分)
      - [1.4.2.1 离线部分](#1421-离线部分)
      - [1.4.2.1 在线部分](#1421-在线部分)


# 一、系统需求

## 1.1 需求分析
1.客户发送相关关键字给服务器，获取相关关键字。
2.客户发送查询关键字给服务器，获取相关网页信息。
3.服务器根据关键字，返回客户端相关关键字
4.服务器根据查询关键字，返回客户端相关网页信息。
（总结就两步**关键字给服务器**，获取相关关键字，然后再**发送查询关键字**）

## 1.2消息格式
每个消息都满足以下格式

| 消息内容长度 | 消息ID | 消息内容    |
| ------------ | ------ | ----------- |
| 4字节        | 4字节  |             |

## 1.3 详细定义

| 消息 ID | 消息内容 | 发送方向 | 客户端处理 | 服务器处理 |
| ------- | ------- | ------- | ---------- | ---------- |
| 1       | 关键字 | C->S    | 无        | 保存并处理   |
| 2       | 关键字 | C->S    | 无       | 保存并处理   |
| 100     | 推荐相关关键字     | S->C    | 获取并展示        | 无        |
| 200     | 根据关键字查询的网页信息 | S->C    | 获取并展示 | 无  |

## 1.4 模块划分

### 1.4.1 模块一 关键字推荐服务部分

#### 1.4.1.1 离线部分

1.创建词典，这个是根据语料库来创建的，把语料库中的每个词抽出来，然后后面是出现的次数也就是频率

2.创建索引文件，结构是
```
vector<string,vector<pair<int, double>>>
```
其中string还是词，int是出现在第几篇文档，double则是一个权重，后面有对应的求权重的公式

**离线部分需要用到语料库，与查询词无关**

#### 1.4.1.2 在线部分

1.服务器端框架的话就直接用TcpServer

2.服务器把客户端传来的关键字，从索引中查找与关键字最相近的候选词
  a.优先选最小编辑路径的
  b.最小编辑路径相同情况下选词频大的（用到了词典）
  c.如果b一样那就按照字母表排序来选
获取5个候选词返回给客户端
发送给客户端的数据用json数据包。

3.功能优化
  使用redis缓存来进行优化
  建立中文词典和索引
  分词算法要能扩展到中文
  扩展最小编辑距离算法


### 1.4.2 模块二 网页查询部分

同样也是分为离线和在线部分

#### 1.4.2.1 离线部分

首先根据语料库生成网页库和网页偏移库，然后再去重，最后再建立一个倒排索引。
至于索引为什么叫倒排呢？
如下
正排索引
```
文档1: {nike, shoes, sport}
文档2: {nike, fashion}
文档3: {adidas, sport}
```
倒排索引
```
nike: {文档1, 文档2}
shoes: {文档1}
sport: {文档1, 文档3}
fashion: {文档2}
adidas: {文档3}
```

我们首先通过倒排索引找到网页偏移库，然后再找到网页库。

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oqntmnrnr86l00dit82c.png)

**离线部分的具体实现**

1.建立网页库和网页偏移库
网页库用xml格式来进行存储，分别是docid号、url、title以及content。
```
<doc>
<id>1</docid>
<url>http://baidu.com/</url>
<title>博客榜—查看频道“中国互联网观察”</title>
<content>博客榜—查看频道“中国互联网观察”…</content>
</doc>
```

那么具体来说网页库、网页偏移库是如何建立的呢？**示例如下**
首先假设我们有两篇文档，内容分别是
```
文档1：
【标题】Nike的最新运动鞋
Nike的最新运动鞋非常受欢迎，它们具有创新的设计和舒适的穿着体验。

文档2：
Adidas推出的新款篮球鞋
今年Adidas推出了新款篮球鞋，这款鞋的抓地力和耐用性都得到了消费者的好评。
```
然后我们把这两篇文档分别格式化，创建网页库，如下

```
<doc>
  <docid>1</docid>
  <url>/path/to/document1</url>
  <title>Nike的最新运动鞋</title>
  <content>Nike的最新运动鞋非常受欢迎，它们具有创新的设计和舒适的穿着体验。</content>
</doc>
<doc>
  <docid>2</docid>
  <url>/path/to/document2</url>
  <title>Adidas推出的新款篮球鞋</title>
  <content>今年Adidas推出了新款篮球鞋，这款鞋的抓地力和耐用性都得到了消费者的好评。</content>
</doc>
```
然后我们把上述的格式化的字符串写入网页库文件，记录他们的同时也要记住位置也就是偏移量。
```
1 0
2 300
```
由此就生成了网页库和网页偏移偏移库。

2.去重部分
直接用谷歌的Simhash

3.建立倒排索引
以单词作为索引，文档id作为记录。

```
vector<string,vector<pair<int, double>>>
```
这里面权重值用TF-IDF算法来进行计算。
其中TF-IDF算法的作用就是把一篇文章中的词进行计算重要性，也就是该篇文档中哪些词是最重要的，能够很好的代表文档的主题和特点。

#### 1.4.2.1 在线部分

1.服务器框架部分
直接用TcpServer，进入监听状态等待客户端连接
2.线程池部分，将客户端发来的任务封装成任务给线程池。

3.查询模块，提供网页查询
（1）首先对于每个查询的关键词，我们把它视作一篇文档，同样的也进行TF-IDF进行计算权重，然后把这些权重组成一个向量叫做Base，这个Base等会会与（3）进行计算
（2）通过倒排索引去查网页，只要有一个词不在索引表中，那么就看作没有找到相关的网页
（3）如果我们找到了网页，就需要对网页进行排序，同样的我们对每个网页进行获取查询词的权重，也就是查询词在网页中的重要性，也把它搞一个向量Y，然后我们把每个Y和Base进行计算余弦值，这个值越大说明网页与查询词的相关程度越大，这样的网页会出现在前排的位置。
（4）当我们找到网页之后，还要提取出标题和摘要，然后把这些封装成一个字符串发送给客户端。

4.优化查询模块，提升网页查询效率。