[项目详解][boost搜索引擎#1] 概述 | 去标签 | 数据清洗 | scp

目录

一、前言

二、项目的相关背景

三、搜索引擎的宏观原理

四、搜索引擎技术栈和项目环境

五、正排索引 VS 倒排索引--原理

正排索引

分词

倒排索引

六、编写数据去除标签和数据清洗模块 Parser

1.数据准备

parser

编码

1.枚举文件 EnumFile

2.去标签ParseHtml()

测试

使用SCP命令在两台Linux服务器之间传输文件

适用场景

命令格式

示例

将scp任务放入后台执行


Boost搜索引擎项目的九个步骤~

  1. 项目的相关背景
  2. 搜索引擎的相关宏观原理
  3. 搜索引擎技术栈和项目环境
  4. 正排索引 vs 倒排索引 - 搜索引擎具体原理
  5. 编写数据去标签与数据清洗的模块Parser
  6. 编写建立索引的模块 Index
  7. 编写搜索引擎模块 Searcher
  8. 编写http server模块
  9. 编写前端模块

准备分几篇文章讲解,持续更新中(●'◡'●),会在最后一篇文章中放上项目的gitee~本篇文章先从这几个部分进行实现

一、前言

在日常使用浏览器搜索时,服务器返回的是与搜索关键字相关的网站信息,包括网站标题、内容简述和URL。点击标题后会跳转到对应的网页。常见的搜索引擎如百度、谷歌等覆盖全网信息,而我们的项目是一个小范围的站内搜索引擎,boost库 实现的 boost站内搜索

二、项目的相关背景

什么是Boost库?

  • Boost库是C++的准标准库,提供许多高级功能。
  • 许多Boost组件已被纳入C++11标准。如:哈希、智能指针
  • 更多详情可访问Boost官网。

什么是搜索引擎?

  • 搜索引擎如百度、360、搜狗展示的信息通常 包括网页标题、摘要和URL。
  • 我们设计的搜索引擎将 不包含图片、视频或广告等扩展内容。
  • 搜出来的结果展示都是以,标题+内容摘要+url 组成

为什么要做Boost搜索引擎?

  • Boost库缺乏站内搜索功能。
  • 实现一个类似cplusplus官网的站内搜索功能是有意义的

  • 实现目标:搜索一个关键字,就能够跳转到指定的网页,并显示出来
  • 站内搜索的数据量相对较小且更垂直化。

三、搜索引擎的宏观原理

通过以下步骤实现:

  1. 数据准备:获取并存储Boost文档数据。我们可以直接将 boost库 对应版本的数据直接解压到我们对应文件里。
  2. 去标签 & 数据清洗提取所需信息(标题、摘要、URL)。我们从boost库拿的数据其实就是对应文档html网页,但是我们需要的只是每个网页的标题+网页内容摘要+跳转的网址,所以才有了去标签和数据清洗(只拿我们想要的
  3. 构建索引:对清洗后的数据建立索引(方便客户端快速查找);
  4. 用户请求处理:解析搜索关键词,检索索引,返回结果。

流程模拟:

  • 当服务器所以的工作都完成之后,客户端就发起http请求,
  • 通过GET方法,上传搜索关键,
  • 服务器收到了会进行解析,通过客户端发来的关键字 去检索已经构建好的索引,找到了相关的html后
  • 将逐个的将每个网页的标题、摘要和网址拼接起来,构建出一个新的网页,响应给客户端
  • 至此,客户就看到了相应的内容,点击网址就可以跳转到boost库相应的文档位置。

网页概述:

  • tltle
  • 内容摘要
  • url

盈利方式:

  • 推送广告,竞价排名收费

四、搜索引擎技术栈和项目环境

技术栈

  • C/C++/C++11, STL,
  • 相关库
  • Web 前端( HTML5, CSS, JavaScript), jQuery, Ajax。

相关库

  • Boost库(文件遍历)
  • Jsoncpp(json 处理)
  • cppjieba(分词)
  • cpp-httplib(网络库-http 服务)

项目环境

  • Ubuntu 云服务器,
  • vim/gcc/g++/Makefile
  • VS2022 或 VSCode

五、正排索引 VS 倒排索引--原理

  • 正排索引:文档ID-->文档关键词/ 内容。
  • 倒排索引:文档的关键词-->文档ID。

分词

目标文档进行分词:目的:方便建立倒排索引和查找
停止词:了,吗,的,the,a,一般情况我们在分词的时候可以不考虑

正排索引

文档 1

我以后要养一只小猫

文档 2

我以后还要养一只小狗

分词

1:我 /以后 /要养/ 一只/ 小猫

2:我 /以后 /还要养 /一只 /小狗

倒排索引

文档 1,文档 2

以后

文档 1,文档 2

小猫

文档 1

小狗

文档 2

模拟一次查找的过程:

用户输入:关键词->倒排索引中查找->提取出文档ID(1,2)->通过倒排数据找到正排ID->找到文档的内容->title+conent(desc)+url 文档结果进行摘要->通过 json字符串响应回去-->然后在用户的浏览器显示出一个个网页信息

代码实现逻辑:

下载Boost库 -> 解析HTML -> 数据清洗 -> 构建索引 -> 提供搜索接口 -> 显示结果。

  1. 据准备:从Boost官网下载 boost 库,并解压至Linux目录。
  2. 选择所需文件:写一个解析程序从一个个html文件的源码中提取标题、内容和url,将他们保存到硬盘的一个data.txt文件中。
  3. 读取:读取data.txt文件,建立正排和倒排索引,提供索引的接口来获取正排和倒排数据
  4. 数据拷贝:写一个html页面,提供给用户一个搜索功能。然后模拟上述查找过程

六、编写数据去除标签和数据清洗模块 Parser

1.数据准备

  • boost 官⽹: https://www.boost.org/

下载:

之后 rz -E,再解压

⽬前只需要boost_1_86_0/doc/html⽬录下的html⽂件,⽤它来进⾏建⽴索引

将我们所需要的数据源 拷贝到 data目录下的intput目录下--清洗数据完成

parser

这里我是在 vscode 下进行代码编写的,但是需要连接一下云服务器,与 Linux进行同步。 你也可以选择 vim。

基本框架:

  • data/input/ 所有后缀为 html 的文件筛选出来 ---- 清洗数据
  • 然后对筛选好的html文件进行解析(去标签),拆分出标题、内容、网址 ---- 去标签
  • 最后将去标签后的所有html文件的标题、内容、网址处理后,写入到 data/raw_html/raw.txt 下

什么是去标签呢?

举例 nano process.html 查看一下

对数据清洗之后,拿到的全都是 html 文件,此时还需要对 html 文件进行去标签处理,我们这里随便看一个html文件

  • 退出 nano 的方法: Ctrl + X 。做了修改并且想要保存,输入 Y(是),不保存,直接按 N(否)然后回车

  • 我们在 data目录 下的 raw_html目录下 创建有一个 raw.txt文件,用来存储干净的数据文档
  • <> : html的标签,这个标签对我们进行搜索是没有价值的,需要去掉这些标签,一般标签都是成对出现的!但是也有单独出现的,我们也是不需要的。

采用下面的方案:

  • 写入文件中,一定要考虑下一次在读取的时候,也要方便操作!
  • 类似:title\3content\3url \n title\3content\3url \n title\3content\3url \n ...
  • 方便我们getline(ifsream, line),直接获取文档的全部内容:title\3content\3url
  • 文件内按照 \3 作为分割符,每个文件再按照 \n 进行区分

note: vim 下的中文注释:ctrl+space

编码

Boost_Searcher 目录下创建 parser.cpp 文件开始编写框架

三步走:

  • 第⼀步EnumFile(src_path, &files_list): 递归式的把每个html⽂件名带路径,保存到文件 files_list中,⽅便后期进⾏⼀个⼀个的 ⽂件进⾏读取(预处理
  • 第⼆步ParseHtml(files_list, &results): 按照files_list读取每个⽂件,并进⾏解析
  • 第三步SaveHtml(results, output): 把解析完毕的各个⽂件内容,写⼊到output,按照\3作为每个⽂档的分割符
#include <iostream>
#include <string>
#include <vector>// 首先我们肯定会读取文件,所以先将文件的路径名 罗列出来
// 将 数据源的路径 和 清理后干净文档的路径 定义好const std::string src_path = "data/input";          // 数据源的路径
const std::string output = "data/raw_html/raw.txt"; // 清理后干净文档的路径//DocInfo --- 文件信息结构体
typedef struct DocInfo
{std::string title;   //文档的标题std::string content; //文档的内容std::string url;     //该文档在官网当中的url
}DocInfo_t;// 命名规则
// const & ---> 输入
// * ---> 输出
// & ---> 输入输出//把每个html文件名带路径,保存到files_list中
bool EnumFile(const std::string &src_path, std::vector<std::string> *files_list);//按照files_list读取每个文件的内容,并进行解析
bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results);//把解析完毕的各个文件的内容写入到output
bool SaveHtml(const std::vector<DocInfo_t> &results, const std::string &output);int main()
{std::vector<std::string> files_list; // 将所有的 html文件名保存在 files_list 中// 第一步:递归式的把每个html文件名带路径,保存到files_list中,方便后期进行一个一个的文件读取// 从 src_path 这个路径中提取 html文件,将提取出来的文件存放在 string 类型的 files_list 中if(!EnumFile(src_path, &files_list)) //EnumFile--枚举文件{std::cerr << "enum file name error! " << std::endl;return 1;}return 0;// 第二步:从 files_list 文件中读取每个.html的内容,并进行解析std::vector<DocInfo_t> results;// 从 file_list 中进行解析,将解析出来的内容存放在 DocInfo 类型的 results 中if(!ParseHtml(files_list, &results))//ParseHtml--解析html{std::cerr << "parse html error! " << std::endl;return 2;}// 第三部:把解析完毕的各个文件的内容写入到output,按照 \3 作为每个文档的分隔符// 将 results 解析好的内容,直接放入 output 路径下if(!SaveHtml(results, output))//SaveHtml--保存html{std::cerr << "save html error! " << std::endl;return 3;}return 0;
}

主要实现:枚举文件、解析html文件、保存html文件三个工作。

这三个工作完成是需要我们使用boost库当中的方法的,我们需要安装一下boost的开发库:

通过如上命令,我是已经安装过啦~

图就是我们接下来编写代码需要用到的 boost库 当中的 filesystem方法。

1.枚举文件 EnumFile
  • 使用 boost 枚举文件名
//在原有的基础上添加这个头文件
#include <boost/filesystem.hpp>//把每个html文件名带路径,保存到files_list中
bool EnumFile(const std::string &src_path, std::vector<std::string> *files_list)
{// 简化作用域的书写namespace fs = boost::filesystem;fs::path root_path(src_path); // 定义一个path对象,枚举文件就从这个路径下开始// 判断路径是否存在if(!fs::exists(root_path)){std::cerr << src_path << " not exists" << std::endl;return false;}// 对文件进行递归遍历fs::recursive_directory_iterator end; // 定义了一个空的迭代器,用来进行判断递归结束  -- 相当于 NULLfor(fs::recursive_directory_iterator iter(root_path); iter != end; iter++){// 判断指定路径是不是常规文件,如果指定路径是目录或图片直接跳过if(!fs::is_regular_file(*iter)){continue;}// 如果满足了是普通文件,还需满足是.html结尾的// 如果不满足也是需要跳过的// ---通过iter这个迭代器(理解为指针)的一个path方法(提取出这个路径)// ---然后通过extension()函数获取到路径的后缀if(iter->path().extension() != ".html"){continue;}//std::cout << "debug: " << iter->path().string() << std::endl; // 测试代码// 走到这里一定是一个合法的路径,以.html结尾的普通网页文件files_list->push_back(iter->path().string()); // 将所有带路径的html保存在files_list中,方便后续进行文本分析}return true;
}
  • makefile 中连接 boost 库

查看对外部库的连接:

运行:

  • 成功提取出了 html 文件~
  • 测试成功后,将测试代码注释掉哦!
  • 运行测试成功,继续编写下一个模块

2.去标签ParseHtml()

解析html文件

  1. 读取刚刚枚举好的文件
  2. 解析html文件中的title
  3. 解析html文件中的content
  4. 解析html文件中的路径,构建url

  • 函数建构
bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results)
{for(const std::string &file : files_list){// 1.读取文件,Read()std::string result;if(!ns_util::FileUtil::ReadFile(file, &result)){continue;}// 2.解析指定的文件,提取titleDocInfo_t doc;if(!ParseTitle(result, &doc.title)){continue;}// 3.解析指定的文件,提取contentif(!ParseContent(result, &doc.content)){continue;}// 4.解析指定的文件路径,构建urlif(!ParseUrl(file, &doc.url)){continue;        }// 到这里,一定是完成了解析任务,当前文档的相关结果都保存在了doc里面results->push_back(std::move(doc)); // 本质会发生拷贝,效率肯能会比较低,这里我们使用move后的左值变成了右值,去调用push_back的右值引用版本}return true;                                                                                                                                                                                                                                                    
}

主要完成 4件事:

①根据路径名依次读取文件内容,②提取title,③提取content,④构建url。


2.1读取文件ReadFile()

  • 遍历 files_list 中存储的文件名,从中读取文件内容到 result 中,由函数 ReadFile() 完成该功能。该函数定义于头文件 util.hpp的类 FileUtil中。
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <vector>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)) 
//如何理解getline读取到文件结束呢??getline的返回值是一个&,while(bool), 本质是因为重载了强制类型转化{*out += line;}in.close();return true;}};
}

⭕ 重点理解:C++的流读取 && getline 的使用

2.2 提取title —— ParseTitle()

  • 可以发现<title>标题</title> 构成的
  • find(<title>)就能找到这个标签的左尖括号的位置
  • 然后加上<title>的长度,此时就指向了标题的起始位置
  • 同理,再去找到</title>的左尖括号,最后截取子串;

这里需要依赖函数 —— bool ParseTitle(const std::string& file,&doc.title),

//解析title
static bool ParseTitle(const std::string& file,std::string* title)
{// 查找 <title> 位置std::size_t begin = file.find("<title>");if(begin == std::string::npos){return false;}// 查找 </title> 位置std::size_t end = file.find("</title>");if(end == std::string::npos){return false;}// 计算中间的距离,截取中间的内容begin += std::string("<title>").size();if(begin > end){return false;}*title = file.substr(begin, end - begin);return true;
}

2.3 提取content--ParseContent()

用一个简易的状态机来完成,状态机包括两种状态:LABLE(标签)和CONTENT(内容);

  • 起始肯定是标签,我们逐个字符进行遍历判断
  • 如果遇到“>”表明下一个即将是内容了,我们将状态机置为CONTENT,接着将内容保存起来
  • 如果此时遇到了“<”,表明到了标签了,我们再将状态机置为LABLE
  • 不断的循环,知道遍历结束;
//去标签 -- 数据清洗
static bool ParseContent(const std::string& file,std::string* content)
{//去标签,基于一个简易的状态机enum status // 枚举两种状态{                                                                                                                                                                                 LABLE,   // 标签CONTENT  // 内容};enum status s = LABLE;  // 刚开始肯定会碰到 "<" 默认状态为 LABLEfor(char c : file){// 检测状态switch(s){case LABLE:if(c == '>') s = CONTENT;break;case CONTENT:if(c == '<') s = LABLE;else {// 我们不想保留原始文件中的\n,因为我们想用\n作为html解析之后的文本的分隔符if(c == '\n') c = ' ';content->push_back(c);}break;default:break;}}return true;
}

2.4 解析 html 的 url

  • boost库 在网页上的 url,和我们 下载的文档的路径有对应关系

探寻官方文档路径和我们路径的关系,以 Accumulators.html 为例

在我们路径下的查找

在 input 中

我们之前已经定义好了两个路径嘛!源数据路径 清理后干净文档的路径

1. 拿 官网的部分网址作为 头部的 url

  • url_head = "https://www.boost.org/doc/libs/1_86_0/doc/html"

2. 将我们项目的路径 data/input 删除后得到 /accumulators.html;

  • url_tail = [data/input(删除)] /accumulators.html -> url_tail = /accumulators.html;

3. 将 url_head + url_tail == 官网的 url

//构建官网url :url_head + url_tail
static bool ParseUrl(const std::string& file_path,std::string* url)
{std::string url_head = "https://www.boost.org/doc/libs/1_85_0/doc/html";    std::string url_tail = file_path.substr(src_path.size());//将data/input截取掉    *url = url_head + url_tail;//拼接return true;
}

到这里我们写的 ParseHtml 解析部分就已经写完啦,那定是我们要先测试一下它的正确性啦!

测试

  • 向源代码中加入了 ShowDoc 测试代码,测试完注释掉即可
// for debug
void ShowDoc(const DocInfo_t& doc)
{std::cout<<"title: "<<doc.title<<std::endl;std::cout<<"content: "<<doc.content<<std::endl;std::cout<<"url: "<<doc.url<<std::endl;
}//按照files_list读取每个文件的内容,并进行解析
bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results)
{// 首先在解析文件之前,肯定需要 遍历 读取文件for(const std::string &file : files_list){// 1.读取文件,Read() --- 将文件的全部内容全部读出,放到 result 中std::string result;if(!ns_util::FileUtil::ReadFile(file, &result)){continue;}// 2.解析指定的文件,提取titleDocInfo_t doc;if(!ParseTitle(result, &doc.title)){continue;}// 3.解析指定的文件,提取contentif(!ParseContent(result, &doc.content)){continue;}// 4.解析指定的文件路径,构建urlif(!ParseUrl(file, &doc.url)){continue;        }// 到这里,一定是完成了解析任务,当前文档的相关结果都保存在了doc里面results->push_back(std::move(doc)); // 本质会发生拷贝,效率肯能会比较低,这里我们使用move后的左值变成了右值,去调用push_back的右值引用版本// for debug  -- 在测试的时候,将上面的代码改写为 results->push_back(doc);ShowDoc(doc);break;  // 只截取一个文件打印}return true;
}

接下来就可以 make , 然后运行:

  • 为了进一步验证正确性,我们可以将网页复制下来,在浏览器中打开,看是否成功

成功ヾ(≧▽≦*)o


对于项目写有一个重点,就是做好对错误的处理~

遇见的一个小问题:

之前的服务器 free -h 查看后发现,在 vscode 下内存有点不够用,然后换了一台朋友的服务器

所以要传一下之前写的文件

使用SCP命令在两台Linux服务器之间传输文件

适用场景

当你需要将大文件从一台服务器直接传输到另一台服务器,而不想通过本地中转时,可以使用scp(secure copy)命令。

命令格式
scp -r [源文件路径] [目标用户名]@[目标IP]:[目标路径]
  • -r:递归复制整个目录。
  • [源文件路径]:要传输的文件或目录的完整路径。
  • [目标用户名]:接收文件服务器上的用户名。
  • [目标IP]:接收文件服务器的IP地址。
  • [目标路径]:在接收方服务器上存放文件的路径。
示例

假设你要把位于/usr/local/testFile/目录下的所有内容复制到IP为100.10.20.30的目标服务器的/root/目录下,并且目标服务器的登录用户名是root,那么你可以运行以下命令:

scp -r /usr/local/testFile/* root@100.10.20.30:/root/

执行这个命令后,系统会提示你输入目标服务器的用户密码。

将scp任务放入后台执行

如果文件量很大,传输可能需要很长时间。为了不阻塞终端,可以将scp进程放到后台执行:

  1. 暂停任务:按下 Ctrl + Z 暂停当前正在执行的scp任务。
  2. 查看任务:使用 jobs 查看已暂停的任务及其编号。
  3. 后台继续执行:使用 bg %a 命令让任务在后台继续执行,其中ajobs返回的任务编号。
  4. 再次检查状态:再次运行 jobs 可以看到任务现在处于“Running”状态,表示它正在后台执行。

这样,即使关闭终端窗口,文件传输也会继续进行,直到完成。如果你想要终止后台任务,可以使用kill命令加上相应的进程ID。

请注意,在执行任何文件传输操作之前,请确保你有权限访问源和目标服务器,并且目标路径对于指定的用户是可写的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/454256.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件处理新纪元:微信小程序的‘快递员’与‘整理师’

嗨&#xff0c;我是中二青年阿佑&#xff0c;今天阿佑将带领大家如何通过巧妙的文件处理功能&#xff0c;让用户体验从‘杂乱无章’到‘井井有条’的转变&#xff01; 文章目录 微信小程序的文件处理文件上传&#xff1a;小程序的“快递服务”文件下载&#xff1a;小程序的“超…

学习threejs,拉伸几何体THREE.TubeGeometry管道

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️拉伸几何体THREE.TubeGeome…

Git的原理和使用(六)

本文主要讲解企业级开发模型 1. 引入 交付软件的流程&#xff1a;开发->测试->发布上线 上面三个过程可以详细划分为一下过程&#xff1a;规划、编码、构建、测试、发 布、部署和维护 最初&#xff0c;程序⽐较简单&#xff0c;⼯作量不⼤&#xff0c;程序员⼀个⼈可以完…

Imagic: Text-Based Real Image Editing with Diffusion Models

https://openaccess.thecvf.com/content/CVPR2023/papers/Kawar_Imagic_Text-Based_Real_Image_Editing_With_Diffusion_Models_CVPR_2023_paper.pdfhttps://imagic-editing.github.io/ 问题引入 针对的是text based image editing问题&#xff0c;可以解决non rigid edit&am…

【软件安装与配置】 vue

1. 安装 Node.js Vue.js 项目通常依赖于 Node.js 环境来进行开发&#xff0c;可以从 Node.js 官方网站 下载并安装稳定版本。安装 Node.js 后&#xff0c;npm&#xff08;Node 包管理器&#xff09;也会自动安装。 2. 使用 Vue CLI 安装 Vue.js Vue CLI 是一个用于快速搭建 Vu…

柔性数组的使用

//柔性数组的使用 #include<stdio.h> #include<stdlib.h> #include<errno.h> struct s {int i;int a[]; }; int main() {struct s* ps (struct s*)malloc(sizeof(struct s) 20 * sizeof(int));if (ps NULL){perror("malloc");return 1;}//使用这…

用.NET开发跨平台应用程序采用 Avalonia 与MAUI如何选择

Avalonia是一个强大的框架&#xff0c;使开发人员能够使用.NET创建跨平台应用程序。它使用自己的渲染引擎绘制UI控件&#xff0c;确保在Windows、macOS、Linux、Android、iOS和WebAssembly等不同平台上具有一致的外观和行为。这意味着开发人员可以共享他们的UI代码&#xff0c;…

容灾与云计算概念

​​​​​​基础知识容灾备份——备份技术系统架构与备份网络方案-CSDN博客 SAN&#xff0c;是storage area network的简称&#xff0c;翻译过来就是存储区域网络。 顾名思义&#xff0c;SAN首先是一个网络&#xff0c;其次它是关于存储的&#xff0c;区域则是指服务器和存储资…

iTOP-RK3568开发板独立NPU通过算法加特应用到以下的场景

iTOP-3568开发板采用瑞芯微RK3568处理器&#xff0c;内部集成了四核64位Cortex-A55处理器。主频高达2.0Ghz&#xff0c;RK809动态调频。集成了双核心架构GPU&#xff0c;ARM G52 2EE、支持OpenGLES1.1/2.0/3.2、OpenCL2.0、Vulkan1.1、内嵌高性能2D加速硬件。 内置独立NPU,算力…

出血性脑卒中临床智能诊疗建模

出血性脑卒中是一种常见但危险的脑血管疾病&#xff0c;其治疗和管理需要及时而准确的诊断以及有效的预测模型。本研究旨在通过分析入院患者的临床数据和影像学特征&#xff0c;建立数学模型&#xff0c;评估患者的血肿扩张风险、血肿周围水肿进展以及长期预后。 针对问题一&a…

15分钟学Go 第8天:控制结构 - 循环

第8天&#xff1a;控制结构 - 循环 在Go语言中&#xff0c;循环是一种基本的控制结构&#xff0c;用于重复执行一段代码。今天我们将深入了解Go语言中的for循环&#xff0c;包括它的各种用法、语法结构、以及如何在实践中有效地应用循环。 1. for 循环的基本概念 for循环是G…

应对 .DevicData-X-XXXXXXXX 勒索病毒:防御与恢复策略

引言 随着信息技术的快速发展&#xff0c;网络安全问题愈发严峻。勒索病毒作为一种恶性网络攻击手段&#xff0c;已成为企业和个人面临的重大威胁之一。尤其是 .DevicData-X-XXXXXXXX 勒索病毒&#xff0c;其通过加密用户数据并勒索赎金&#xff0c;给受害者带来了巨大的经济损…

在Xshell中查看日志文件详情

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

子比主题美化 – 评论区添加随机夸夸功能(修复api)

简介 有很多人在网站浏览需要回复&#xff0c;有的比较嫌麻烦不愿意打字&#xff0c;也会收到一些各种评论相对比较杂乱&#xff0c;今天分享一个用夸夸功能&#xff0c;来替代传统的评论一言&#xff0c;将它们分开使用&#xff0c;先看看效果图&#xff0c;再考虑使用不使用…

基于SpringBoot+Vue+uniapp微信小程序的教学质量评价系统的详细设计和实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

一文详解“位运算“在算法中的应用

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 位运算的相关介绍&#xff08;重要&#xff09; 136. 只出现一次的数字 191.位1的个数 461. 汉明距离 260. 只出现一…

导数的概念及在模型算法中的应用

一. 导数概念与计算 1. 导数的物理意义&#xff1a; 瞬时速率。一般的&#xff0c;函数yf(x)在x处的瞬时变化率是 2. 导数的几何意义&#xff1a; 曲线的切线&#xff0c;当点趋近于P时&#xff0c;直线 PT 与曲线相切。容易知道&#xff0c;割线的斜率是当点趋近于 P 时&…

QT 实现按钮多样化

1.界面实现效果 以下是具体的项目需要用到的效果展示,可以根据需要,实例化想要的按钮。 2.简介 原理:使用Qt的QPropertyAnimation动画类,这里简单来说就是切换两个按钮样式。 请看以下结构体: #define MAX_LINE_COUNT 3struct PurelinStatus {QSizeF bgSize

ABAQUS应用13——大量INP文件的自动提交

文章目录 0、背景1、正文 0、背景 ABAQUS自动批量提交INP文件。原文来自曹老师公众号&#xff0c;感兴趣的可以点击这里。 为了防止遗失&#xff0c;我还是先保存比较好。 1、正文 分析需要对大量 INP 文件进行提交分析&#xff0c;在 Abaqus / CAE 中手动操作无法完成&…

十四、MySQL事务日志

文章目录 1. redo日志1.1 为什么需要REDO日志1.2 REDO日志的好处、特点1.2.1 好处1.2.2 特点1.3 redo的组成1.4 redo的整体流程1.5 redo log 的刷盘策略1.6 不同刷盘策略演示1.7 写入redo log buffer 过程1.7.1 补充概念:Mini-Transaction1.7.2 redo 日志写入log buffer1.7.3 …