python+vue2+nodejs 搜索引擎课设 SCAU数信学院本科生通知检索(附源码)

news2024/11/19 20:41:04

在这里插入图片描述

前言

这个系统主要实现了以下功能:

在这里插入图片描述

  1. 爬虫:数据爬取及分词
  2. 后端:数据库全文模糊搜索、高频词获取
  3. 前端:输入拼音缩写或文字后匹配输入建议、搜索、列表分页、高亮关键词、相关度排序及时间排序、深色模式及浅色模式切换

爬虫:python
后端:nodejs
前端:vue2

这个课设从代码到报告一共用了三天,ddl生死时速,所以很多地方实现得并不好,比如等我都交上去了突然发现没做关键词搜索历史,等我去做机器学习实验的时候才发现关键词自动补全用的是FP-growth算法。不过我确实尽力了,因为老师宽容,加上疫情不考试由课设决定成绩,这门课拿了满绩点,混子人生中第一个满绩点呜呜呜。

爬虫

数据爬取

新闻爬取是参考爬取华农数信院官网的新闻,并且发送到邮箱。

改动在于:

  1. 爬取的字段变为标题、发布时间、描述
  2. 将发送到邮箱改为保存到数据库
  3. 爬取所有新闻而非单页新闻

需要注意的地方是我爬取的时候最后一页是65页,只有5条新闻,这部分需要按照实际情况自己改动。

from bs4 import BeautifulSoup
import requests
from peewee import*
datalist = []
def main():
    for i in range(1, 66):
        getdata(i)
    print("已获取数据")
    # print(datalist)
    savedata(datalist)
    print("已保存数据")

def getdata(page):
    headers = {
        'User - Agent': 'Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 89.0.4389.90 Safari / 537.36 Edg / 89.0.774.54'
    }
    num = 20
    # 最后一页不足20条
    if(page == 65):
        num = 5
    page = str(page)
    # 发送请求获取页面的html
    info = requests.get(url='https://info.scau.edu.cn/3772/list'+page+'.htm', headers=headers)
    info.encoding = 'utf-8'
    # 用BeautifulSoup解析html
    html = BeautifulSoup(info.text, 'html.parser')
    # print(html)
    # result = []
    # 循环拿对应的新闻的标题、日期和链接
    for i in range(0, num):
        title = html.select('.title')[i].text
        date1 = html.select('.date')[i].text
        desc = html.select('.desc')[i].find('a').text
        # a = targetUrl.get('href')
        # prefixUrl = 'https://info.scau.edu.cn'
        # targetUrl = prefixUrl + a
        # print(targetUrl)
        datalist.append({
            "title": title,
            "date": date1,
            "desc": desc
        })
    print(page)
    # return result
        # print(result)


def savedata(data):
    db = MySQLDatabase('scauInfo', host='127.0.0.1', user='mysql用户名', passwd='mysql密码')
    db.connect()
    class BaseModel(Model):
        class Meta:
            database = db  # 每一个继承BaseModel类的子类都是连接db表

    class Info(BaseModel):
        title = CharField()
        date = CharField()
        desc = CharField()

    Info.create_table()
    i = 0
    length = len(data)
    # print(data[0])
    # print(data[0]['title'])
    while i < length:
        Info.create(title=data[i]['title'], date=data[i]['date'], desc=data[i]['desc'])
        i += 1
if __name__ == "__main__":  # 当程序执行时
    # 调用函数
    main()

分词

主要目的就是计算在文章中出现的高频词,存放在关键词列表中,用户搜索的时候可以补全。

关键词补全功能:用户输入拼音缩写或部分关键字时,需要出现模糊匹配的关键词供用户选择,比如用户输入“jxj”或“奖”时,下拉框需要弹出关键词“奖学金”。

问题来了,如何获得"奖学金"这个词,当时的想法有两个:

  • 搜集用户输入的关键词,比如“奖学金”被搜索五次以上就算高频搜索词,将其纳入关键词列表,存进数据库,用户搜索时再将其从数据库中select出来
  • 但是时间短,测试数据有限,所以又想到从文章中搜集出现的高频词汇,存储前120个高频词补充进关键词列表,所以才有分词这个步骤
    在这里插入图片描述
    上面是载入停用词表后用结巴分词的结果,问题有两个:
  • 即使用停用词表筛出了很多没意义的词,但筛选结果还是有很多没意义的词:“我院”,“学年”等等,所以人工将一些词补充进停用词表
  • 分词不准确,比如“蓝桥杯”和“线上赛”被分开了,解决方法是人工观察结果,自定义一个分词表
from peewee import*
import jieba
import re

title = []
# date = []
desc = []
words = []
no_stop_words = []
new_a = {}
db = MySQLDatabase('scauInfo', host='127.0.0.1', user='mysql用户名', passwd='mysql密码')
db.connect()
class BaseModel(Model):
    class Meta:
        database = db  # 每一个继承BaseModel类的子类都是连接db表

def main():
    getSentence()
    splitSentence()
    useStopWord()
    getTimes()

def getSentence():
    class Info(BaseModel):
        title = CharField()
        date = CharField()
        desc = CharField()
    datas = Info.select()
    for data in datas:
        title.append(data.title)
        # date.append(data.date)
        desc.append(data.desc)

def splitSentence():
    jieba.load_userdict('D:\xxx路径\specialWords.txt')
    for sentence1 in title:
        # 使用jieba进行分词,使用精确模式
        devision_words1 = jieba.cut(sentence1, cut_all=False)
        # 将分词后的结果转化为列表,然后添加到分词列表中
        words.extend(list(devision_words1))
    for sentence2 in desc:
        # 使用jieba进行分词,使用精确模式
        devision_words2 = jieba.cut(sentence2, cut_all=False)
        # 将分词后的结果转化为列表,然后添加到分词列表中
        words.extend(list(devision_words2))
    # print(words)

def useStopWord():
    stop_path = r"D:\xxx路径\stopWord.txt"  # 停用词表的位置
    stop_list = []
    for line in open(stop_path, 'r', encoding='utf-8').readlines():
        stop_list.append(line.strip())

    for word in words:  # 使用分词后的结果然后用空格进行分割,得到每个分词
        if word not in stop_list:  # 如果这个分词不在停用词表中并且不是换行或者制表符就将其加入到最后的字符串中,然后加一个空格
            word = re.sub(r'\d', "", word)  # 去除单词中的数字
            word = re.sub(r'\s', "", word)  # 去除单词中的空格
            word = re.sub(r'\W', "", word)  # 去除单词中的字母
            if word:
                if(len(word) > 1):
                    no_stop_words.append(word)

def getTimes():
    # 统计每一个单词的出现次数,使用字典的形式进行统计
    result = {}
    for word in no_stop_words:
        res = result.get(word, 0)
        if res == 0:
            result[word] = 1
        else:
            result[word] = result[word] + 1

    result = sorted(result.items(), key=lambda kv: (kv[1], kv[0]), reverse=True)
    result = dict(result)
    for i, (k, v) in enumerate(result.items()):
        new_a[k] = v
        if i == 119:
            saveWords(list(new_a.keys()))
            # print(new_a.keys())
            break
    new_a.clear()

def saveWords(data):
    class highFreWords (BaseModel):
        word = CharField()
    highFreWords.create_table()
    i = 0
    length = len(data)
    while i < length:
        highFreWords.create(word=data[i])
        i += 1

# def getAllFrequency:
#     # 统计词频,使用上一问得到的字典
#     cum2 = {}
#     sum = 0
#     new_a.clear()
#     for i, (k, v) in enumerate(fre2.items()):
#         sum = sum + v
#         new_a[k] = sum
#     cum2 = new_a.copy()
#
# def getEveryFrequency:
#     # 使用字典得到的累计词频结果:
#     for i, (k, v) in enumerate(cum2.items()):
#         new_a[k] = v
#         if i == 9:
#             print(new_a)
#             break


if __name__ == "__main__":  # 当程序执行时
    # 调用函数
    main()

数据库结构

如果照上面代码运行数据库结构应该是这样的:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

后端

用nodejs写了两个接口:

  • 全文模糊搜索接口
  • 获取文章高频关键词及用户搜索高频词接口

全文模糊搜索接口:接收前端传来的参数:关键词(keyWords)、排序方式(sortType)、当前页数(curPage)。

(1) 当关键词(keyWords)为“%%”时,表示用户未进行搜索或输入关键词为空,此时应当返回按时间降序排列的所有通知:写出筛选语句,用“date desc”控制按照时间降序返回数据,当时间相同时,根据id正序返回数据。向数据库发起查询请求,如果出错则将错误抛出。获取数据总条数,按照每页20条的规则用splice方法及前端传来的curPage对数据进行切分。最后向前端返回表示处理成功的200状态码、消息提示、切分好的数据及数据总条数。

(2) 当关键词(keyWords)不为“%%”时,表示用户输入了关键词,此时先用nodejieba将关键词进行分词,如“奖学金公示”会被划分为“奖学金”和“公示”,接着用slice().join()将数组转为用“|”连接的字符串。先从userInput表中筛选此关键词是否存在在表中,如果不存在,将关键词插入表中,times字段赋值为1,表明此关键词被搜索过一次,否则更新表,将对应的times字段值加1,表明此关键词被搜索次数增加一次。当sortType为0时,表示按照相关度返回模糊匹配的数据:用正则表达式将标题、日期、描述中字段含有关键词的部分找到(即模糊搜索),再从其中计算它们的出现次数作为keyweight,按照出现次数降序排序获取数据;当sortType为1时,表示按照时间降序返回模糊匹配的数据:用正则表达式将标题、日期、描述中字段含有关键词的部分找到,按照时间字段降序排序获取数据。获取数据总条数,按照每页20条的规则用splice方法及前端传来的curPage对数据进行切分。最后向前端返回表示处理成功的200状态码、消息提示、切分好的数据及数据总条数。

获取文章高频关键词及用户搜索高频词接口:
(1) 获取文章高频关键词:写出筛选语句获取highFreWords表中所有高频关键词,获取失败则抛出错误。用map方法遍历数据项将其中的”word”属性转为”value”属性。

(2) 获取用户搜索高频词:写出筛选语句获取userInput表中times字段值大于5的关键词,获取失败则抛出错误。用map方法及replace方法遍历数据项将其中的”word”属性转为”value”属性,“|”分隔符转换为空格。

向前端返回表示处理成功的200状态码、消息提示、转化完成的数据。

const express = require("express")
const app = express()
const mysql = require("mysql")
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

const { load, cut } = require('@node-rs/jieba')
load()

app.listen(3000, () => {
  console.log("服务器开启3000端口...")
})

// 创建与数据库的连接
var connection = mysql.createConnection({
  host: '127.0.0.1',
  user: "用户名",
  password: '密码',
  database: "scauInfo",
  port: '3306'
})

connection.connect((err) => {
  if (err) throw err
  console.log("连接成功")
})

// 全表模糊查询
app.post('/search', function (req, res) {
  let keyWords = req.body.keyWords
  let sortType = req.body.sortType
  let curPage = Number(req.body.curPage)
  if (keyWords == '%%') {
    let selectSQL = "select * from Info order by date desc, id"
    connection.query(selectSQL, function (err, rows, fields) {
      if (err) throw err
      let total = rows.length
      let pageSize = 20
      let data = rows.splice((curPage - 1) * pageSize, pageSize)
      res.send({ status: 200, message: 'get searchList', data: data, total: total })
    })
  }
  else {
    let tmp = cut(keyWords, false)
    splitKeyWords = tmp.slice(1, tmp.length - 1).join("|")
    let sql1 = "select * from userInput where words = '" + splitKeyWords + "'"
    connection.query(sql1, function (err, rows, fields) {
      if (err) throw err
      if (rows.length == 0) {
        sql2 = "insert into userInput(words,times) values('" + splitKeyWords + "',1)"
        connection.query(sql2, function (err, rows, fields) {
          if (err) throw err
        })
        return
      }
      let sql3 = "update userInput set times  = times + 1 where words = '" + splitKeyWords + "'"
      connection.query(sql3, function (err, rows, fields) {
        if (err) throw err
      })
    })
    // console.log('keywords', splitKeyWords)
    let selectSQL = ""
    if (sortType == 0) {
      selectSQL = "SELECT *,((IF( title REGEXP '" + splitKeyWords + "', 1, 0))+(IF( date REGEXP '" + splitKeyWords + "', 1, 0)) + (IF( `desc` REGEXP '" + splitKeyWords + "', 1, 0))) AS keyweight FROM Info WHERE CONCAT_WS(' ', title, date, `desc`) REGEXP '" + splitKeyWords + "' ORDER BY keyweight DESC"

    } else {
      selectSQL = "select * from Info where title REGEXP '" + splitKeyWords + "' or date REGEXP '" + splitKeyWords + "' or `desc` REGEXP '" + splitKeyWords + "' order by date desc, id"
    }
    console.log("selectSQL", selectSQL)
    connection.query(selectSQL, function (err, rows, fields) {
      if (err) throw err
      if (rows.length == 0) {
        res.send({ status: 404, message: '暂无搜索结果' })
        return
      }
      let total = rows.length
      let pageSize = 20
      let data = rows.splice((curPage - 1) * pageSize, pageSize)
      res.send({ status: 200, message: 'get searchList', data: data, total: total, splitKeyWords: splitKeyWords })
    })
  }
})

app.get('/getSuggestWords', function (req, res) {
  let selectSQL1 = "select word from highFreWords"
  connection.query(selectSQL1, function (err, rows, fields) {
    if (err) throw err
    let data1 = rows.map((item) => {
      return {
        value: item['word']
      }
    })
    let selectSQL2 = "select words from userInput where times > 5"
    connection.query(selectSQL2, function (err, rows, fields) {
      if (err) throw err
      let data2 = rows.map((item) => {
        return {
          value: item['words'].replace('|', ' ')
        }
      })
      data1 = data1.concat(data2)
      res.send({ status: 200, message: 'get suggestWords', data: data1 })
    })
  })
})

前端

组件库用的是elementui

输入拼音缩写或文字后匹配输入建议功能

组件使用autocomplete,拼音匹配用的库是pinyin-match,实现关键点是模糊匹配

在这里插入图片描述

搜索功能

当用户点击输入建议的下拉框列表项或搜索按钮时,由于要请求接口返回新数据,先将控制加载图标显示的变量设为true,并重置分页列表中当前页数为1,使用正则表达式去除输入关键词中的空格,将处理好的关键词发送给后端,由后端对数据库进行全文模糊搜索,返回筛选出的通知列表给前端,再由前端接收搜索结果列表并更新展示在结果页。

在这里插入图片描述

列表分页功能

分页组件是el-pagination。设定分页模式、每页展示的通知列表条数,初始页码及列表总数。列表总数通过调用搜索接口,由后端返回通知列表总数获得。通过current-change事件监听用户翻页,更新当前页码后调用搜索接口获取更新后的通知列表并显示在页面上。
在这里插入图片描述

高亮关键词功能

当搜索接口返回经过分词处理的关键词列表后,用正则表达式将其从段落中选择出来,为避免搜索结果不区分大小写,使用函数形式及模板字符串,将关键词字段替换为html语句,为其加上红色的css属性,使用v-for遍历通知列表,使用v-html解析html代码,将标题,日期,描述中出现的关键字展示出来。
在这里插入图片描述

相关度排序及时间排序功能

当用户未进行搜索,通知列表默认按时间排序,用v-show隐藏el-select组件;当用户进行搜索并且结果已经展示在页面时,提供排序功能,显示el-select组件,下拉框中绑定选项列表,列表数组的每一项由value和label组成的对象构成。用户可以选择相关度排序或时间排序label,当监听到用户选择的选项有变动时,获取用户选项值中label对应的value,并调用搜索接口将用户选项value传递给后端,规定传递的值value为0时为按相关度排序,当传递的值value为1时按时间排序。前端将后端返回的已排序好的结果展示在页面。

在这里插入图片描述

深色模式及浅色模式切换功能

首先用v-deep更改组件样式,隐藏未选择项:设置其颜色为透明;设置active-color及inactive-color作为切换选择器的颜色。安装scss预处理器后在assets文件夹下建立_themes.scss用于配置不同的主体配色方案,将对应主体的颜色变量集合存放在$themes中。在assets文件夹下建立_handle.scss用于操作主题变量,用@mixin定义可重复使用的样式,遍历主题,将局部变量提升为全局变量,再用插值表达式判断html中data-theme的属性值。声明一个根据key获取颜色的方法,用@include引用混合样式。在页面的vue文件下的style中先引入对应的_handle.scss文件,并根据需求在对应地方引入对应的混入器。使用el-switch组件为用户提供一个开关,通过监听用户的操作:如用户打开开关,此时值为true,将表示主题的变量设置为light,并给页面节点设置data-theme为light的属性,实现浅色模式切换,反之亦然。
在这里插入图片描述

效果展示

输入拼音缩写匹配输入建议

在这里插入图片描述

输入文字匹配输入建议

在这里插入图片描述

关键字高亮

在这里插入图片描述

按时间排序

在这里插入图片描述

** 按相关性排序**

在这里插入图片描述

列表分页

在这里插入图片描述

日间(浅色)模式

在这里插入图片描述

夜间(深色)模式

在这里插入图片描述

最后

项目已上传至搜索引擎课设 SCAU数信学院本科生通知检索,欢迎star!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

兔八哥与猎人

兔八哥与猎人 题目描述 兔八哥躲藏在树林旁边的果园里。果园有 MNM \times NMN 棵树&#xff0c;组成一个 MMM 行 NNN 列的矩阵&#xff0c;水平或垂直相邻的两棵树的距离为 111。兔八哥在一棵果树下。 猎人背着猎枪走进了果园&#xff0c;他爬上一棵果树&#xff0c;准备杀…

springboot整合JSR303校验

4.7 JSR303校验 4.7.1 统一校验的需求 前端请求后端接口传输参数&#xff0c;是在controller中校验还是在Service中校验&#xff1f; 答案是都需要校验&#xff0c;只是分工不同。 Contoller中校验请求参数的合法性&#xff0c;包括&#xff1a;必填项校验&#xff0c;数据…

Python_内置函数

1、abs()&#xff1a;绝对值 2、all()&#xff1a;接受一个可迭代对象&#xff0c;如果对象里的所有元素的bool运算值都是True&#xff0c;那么返回True,否则返回False 3、any()&#xff1a;接受一个可迭代对象&#xff0c;如果对象里有一个元素的bool运算值都是True&#xff0…

CSS实现从下至上弹出的抽屉动画

从下至上展开抽屉动画<!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport" content"initial-scale1.0, maximum-scale1.0, user-scalableno" /><title></title><style>.co…

码农抓取商品详情API调用,Json和XML等格式

API 指的 是一些预定义的函数&#xff0c; 可以 提供给应用程序和开发人员基于软件或硬件访问一组例程的 功能 &#xff0c; 而 不再需要访问源代码或理解内部工作机制细节。 API 可以用于 于开发使用相同数据的其他应用程序&#xff0c;比如公司&#xff0c;他们可以创建一个A…

携手向前,欧拉沙龙双品牌联合运营纯电赛道再提速

面对波诡云谲的市场环境和竞争格局&#xff0c;企业只有不断变革&#xff0c;才能赢得更多的发展机遇&#xff0c;拥有属于自己的生存空间。 在2022年12月底广州国际车展和今年1月初的海口新能源车展上&#xff0c;欧拉携好猫、好猫GT、芭蕾猫、闪电猫&#xff0c;沙龙携高端车…

【Linux】-- 进程程序替换

目录 引入进程程序替换 进程程序替换 初步使用exec系列函数 原理分析 做一个简易的shell cd - 内置命令的理解 export - 环境变量的深入理解 引入进程程序替换 对于fork的学习让我们知道&#xff1a;fork()之后的&#xff0c;父子进程各自执行父进程代码的一部分。但是创…

IO初识233

绝对路径和相对路径 路径是用来描述一个文件在电脑上的具体位置。 这里的 E:\绘画合集\CCE展会logo 2.0就是绝对路径 目录之间的分隔符可以用\也可以用/来表示 相对路径就是以一个基准路径&#xff08;工作路径&#xff09;&#xff0c;以基准路径为起点往下走要怎么表示目标…

Java字符串训练

Java字符串训练一、用户登录二、统计字符次数三、拼接字符串1. 使用String2. 使用StringBuilder四、字符串反转五、金额转换六、手机号屏蔽七、身份证信息查看八、敏感词替换九、对称字符串十、数字转罗马数字十一、调整字符串十二、打乱字符串一、用户登录 需求&#xff1a;已…

MySQL监控(一):了解SigNoz

1.SigNoz介绍 github SigNoz SigNoz官方文档 2022 年 11 大 MYSQL 监控工具 MySQL | 六个最常用的 MySQL 数据库监控工具 2.SigNoz安装 从官方文档上得知使用以下命令进行安装&#xff1a; git clone -b main https://github.com/SigNoz/signoz.git && cd signoz/d…

SpringSecurity(十三)【授权】

十三、授权 什么是授权权限管理核心概念Spring Security 权限管理策略基于 URL 地址的权限管理基于方法的权限管理实战 权限管理 身份认证&#xff0c;就是判断一个用户是否为合法用户的处理过程。SpringSecurity中支持多种不同方式的认证&#xff0c;但是无论开发者使用那种方…

【uniapp】uniapp使用高德地图定位打包成安卓app的一些记录,比如打包后定位失效、

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、创建你的uniapp1.打开Dcloud开发者后台2.下载你的证书、获取你的SHA1安全码、证书私钥密码二、打开高德开放平台申请key1.打开官网2.创建一个应用三、在unia…

快速傅里叶变换FFT和逆变换的python编程

0. 预备知识 快速傅里叶变换旨在解决离散傅里叶变换DFT计算量大效率低的问题。当我们想要抑制噪声提取出某段信号中的有效信息时&#xff0c;如系统模型辨识或者是使用高精度力传感器测量人体腕部寸关尺脉搏信号这类应用&#xff0c;应该如何设计采样流程&#xff1f; 首先&a…

《通讯录》思路及代码实现详解

目录 一、通讯录功能实现的详细描述 二、通讯录的代码及思路实现 2、1 定义联系人结构体 2、2 初始化就结构体与释放动态开辟空间的实现 2、3 菜单打印 2、4 添加联系人信息 2、5 删除联系人信息 2、6 查询联系人信息 2、7 修改联系人信息 2、8 打印所有联系人信息 2、9 排序整…

75. 序列模型的代码实现

1. 训练 在了解了上述统计工具后&#xff0c;让我们在实践中尝试一下&#xff01; 首先&#xff0c;我们生成一些数据&#xff1a;(使用正弦函数和一些可加性噪声来生成序列数据&#xff0c; 时间步为 1,2,…,1000 。) %matplotlib inline import torch from torch import nn…

新手nvm npm 卸载不用依赖包,项识别为 cmdlet、函数、脚本文件,等命令集合

nvm安装包&#xff1a;Releases coreybutler/nvm-windows GitHub下载ta就不用单独下载node了注意:vnm安装位置尽量不要动C:\Users\Administrator\AppData\Roaming\nvm\settings.txt增加下面代码node_mirror: https://npm.taobao.org/mirrors/node/ npm_mirror: https://npm.t…

java+Springboot交通事故档案管理系统

系统分为用户和管理员两个角色 用户的主要功能有&#xff1a; 1.用户注册和登陆系统 2.用户查看警察相关信息 3.用户查看我的相关事故信息&#xff0c;可以对交通事故进行交通申诉 4.用户查看交通申诉审核信息 5.退出登陆 管理员的主要功能有&#xff1a; 1.管理员输入账户登陆…

Metasploit渗透框架介绍及永恒之蓝复现

Metasploit渗透框架介绍及永恒之蓝复现一、Metasploit渗透框架介绍1.1 名词解释1.2 MSF简介1.3 MSF框架结构1.4 MSF命令汇总1.4.1 常用命令1.4.2 基本命令1.4.3 Exploits模块1.4.4 漏洞名称规则1.5 MSF模块介绍1.5.1 auxiliary(辅助模块)1.5.2 exploits(漏洞利用模块)1.5.3 pay…

Open3D 泊松盘网格采样(Python版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在图形的许多应用中,特别是在渲染中,从蓝色噪声分布生成样本是很重要的。然而,现有的有效技术不容易推广到二维以外。不过泊松盘采样是个例外,它允许在O(N)时间内生成泊松盘样本,而且该方法很容易在任意维度上…

分布式CAP和BASE理论学习笔记

参考至&#xff1a;https://blog.csdn.net/solihawk/article/details/124442443 1. CAP理论 CAP理论是计算机科学家Eric Brewer在2000年提出的理论猜想&#xff0c;在2002年被证明并成为分布式计算领域公认的定理&#xff0c;其理论的基本观念是&#xff0c;在分布式系统中不…