挑战杯 python的搜索引擎系统设计与实现

2024-02-16 23:28

本文主要是介绍挑战杯 python的搜索引擎系统设计与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0 前言

🔥 优质竞赛项目系列,今天要分享的是

🚩 python的搜索引擎系统设计与实现

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:5分
  • 创新点:3分

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate


1 课题简介

随着互联网和宽带上网的普及, 搜索引擎在中国异军突起, 并日益渗透到人们的日常生活中, 在互联网普及之前,
人们查阅资料首先想到的是拥有大量书籍的资料的图书馆。 但是今天很多人都会选择一种更方便、 快捷、 全面、 准确的查阅方式–互联网。
而帮助我们在整个互联网上快速地查找到目标信息的就是越来越被重视的搜索引擎。

今天学长来向大家介绍如何使用python写一个搜索引擎,该项目常用于毕业设计


在这里插入图片描述

2 系统设计实现

2.1 总体设计

学长设计的系统采用的是非关系型数据库Elasticsearch,因此对于此数据库的查询等基本操作会加以图例的方式进行辅助阐述。在使用者开始进行査询时,系统不可能把使用者输入的关键词与所有本地数据进行匹配,这种检索方式即便建立索引,查询效率仍然较低,而且非常消耗服务器资源。

因此,Elasticsearch将获取到的数据分为两个阶段进行处理。第一阶段:采用合适的分词器,将获取到的数据按照分词器的标准进行分词,第二阶段:对每个关键词的频率以及出现的位置进行统计。

经过以上两个阶段,最后每个词语具体出现在哪些文章中,出现的位置和频次如何,都将会被保存到Elasticsearch数据库中,此过程即为构建倒排索引,需要花费的计算开销很大,但大大提高了后续检索的效率。其中,搜索引擎的索引过程流程图如图

在这里插入图片描述

2.2 搜索关键流程

如图所示,每一位用户在搜索框中输入关键字后,点击搜索发起搜索请求,系统后台解析内容后,将搜索结果返回到查询结果页,用户可以直接点击查询结果的标题并跳转到详情页,也可以点击下一页查看其他页面的搜索结果,也可以选择重新在输入框中输入新的关键词,再次发起搜索。

跳转至不同结果页流程图:

在这里插入图片描述

浏览具体网页信息流程图:

在这里插入图片描述

搜索功能流程图:
在这里插入图片描述

2.3 推荐算法

用户可在平台上了解到当下互联网领域中的热点内容,点击文章链接后即可进入到对应的详情页面中,浏览选中的信息的目标网页,详细了解其中的内容。丰富了本搜索平台提供信息的实时性,如图

在这里插入图片描述

用户可在搜索引擎首页中浏览到系统推送的可能感兴趣的内容,同时用户可点击推送的标题进入具体网页进行浏览详细内容。流程图如图

在这里插入图片描述

2.4 数据流的实现

学长设计的系统的数据来源主要是从发布互联网专业领域信息的开源社区上爬虫得到。

再经过IK分词器对获取到的标题和摘要进行分词,再由Elasticsearch建立索引并将数据持久化。

用户通过输入关键词,点击检索,后台程序对获得的关键词再进行分词处理,再到数据库中进行查找,将满足条件的网页标题和摘要用超链接的方式在浏览器中显示出来。

在这里插入图片描述

3 实现细节

3.1 系统架构

搜索引擎有基本的五大模块,分别是:

  • 信息采集模块
  • 信息处理模块
  • 建立索引模块
  • 查询和 web 交互模块

学长设计的系统目的是在信息处理分析的基础上,建立一个完整的中文搜索引擎。

所以该系统主要由以下几个详细部分组成:

  • 爬取数据
  • 中文分词
  • 相关度排序
  • 建立web交互。

3.2 爬取大量网页数据

爬取数据,实际上用的就是爬虫。

我们平时在浏览网页的时候,在浏览器里输入一个网址,然后敲击回车,我们就会看到网站的一些页面,那么这个过程实际上就是这个浏览器请求了一些服务器然后获取到了一些服务器的网页资源,然后我们看到了这个网页。

请求呢就是用程序来实现上面的过程,就需要写代码来模拟这个浏览器向服务器发起请求,然后获取这些网页资源。那么一般来说实际上获取的这些网页资源是一串HTML代码,这里面包含HTML标签,还有一

我们写完程序之后呢就让它一直运行着,它就能代替我们浏览器来向服务器发送请求,然后一直不停的循环的运行进行批量的大量的获取数据了,这就是爬虫的一个基本的流程。

一个通用的网络爬虫的框架如图所示:

在这里插入图片描述
这里给出一段爬虫,爬取自己感兴趣的网站和内容,并按照固定格式保存起来:

# encoding=utf-8# 导入爬虫包from selenium import webdriver
​    # 睡眠时间import time
​    import re
​    import os
​    import requests
​    # 打开编码方式utf-8打开# 睡眠时间 传入int为休息时间,页面加载和网速的原因 需要给网页加载页面元素的时间def s(int):time.sleep(int)​     
​    # html/body/div[1]/table/tbody/tr[2]/td[1]/input# http://dmfy.emindsoft.com.cn/common/toDoubleexamp.doif __name__ == '__main__':#查询的文件位置# fR = open('D:\\test.txt','r',encoding = 'utf-8')# 模拟浏览器,使用谷歌浏览器,将chromedriver.exe复制到谷歌浏览器的文件夹内chromedriver = r"C:\\Users\\zhaofahu\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe"# 设置浏览器os.environ["webdriver.chrome.driver"] = chromedriverbrowser = webdriver.Chrome(chromedriver)# 最大化窗口 用不用都行browser.maximize_window()#  header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}# 要爬取的网页neirongs = []  # 网页内容response = []  # 网页数据travel_urls = []urls = []titles = []writefile = open("docs.txt", 'w', encoding='UTF-8')url = 'http://travel.yunnan.cn/yjgl/index.shtml'# 第一页browser.get(url)response.append(browser.page_source)# 休息时间s(3)# 第二页的网页数据#browser.find_element_by_xpath('// *[ @ id = "downpage"]').click()#s(3)#response.append(browser.page_source)#s(3)# 第三页的网页数据#browser.find_element_by_xpath('// *[ @ id = "downpage"]').click()#s(3)#response.append(browser.page_source)​     
​        # 3.用正则表达式来删选数据
​        reg = r'href="(//travel.yunnan.cn/system.*?)"'# 从数据里爬取data。。。# 。travel_urls 旅游信息网址for i in range(len(response)):
​            travel_urls = re.findall(reg, response[i])# 打印出来放在一个列表里for i in range(len(travel_urls)):url1 = 'http:' + travel_urls[i]urls.append(url1)browser.get(url1)content = browser.find_element_by_xpath('/html/body/div[7]/div[1]/div[3]').text# 获取标题作为文件名b = browser.page_sourcetravel_name = browser.find_element_by_xpath('//*[@id="layer213"]').texttitles.append(travel_name)print(titles)print(urls)for j in range(len(titles)):writefile.write(str(j) + '\t\t' + titles[j] + '\t\t' + str(urls[j])+'\n')s(1)browser.close()## 

3.3 中文分词

中文分词使用jieba库即可

jieba 是一个基于Python的中文分词工具对于一长段文字,其分词原理大体可分为三步:

1.首先用正则表达式将中文段落粗略的分成一个个句子。

2.将每个句子构造成有向无环图,之后寻找最佳切分方案。

3.最后对于连续的单字,采用HMM模型将其再次划分。

jieba分词分为“默认模式”(cut_all=False),“全模式”(cut_all=True)以及搜索引擎模式。对于“默认模式”,又可以选择是否使用
HMM 模型(HMM=True,HMM=False)。

3.4 相关度排序

上面已经根据用户的输入获取到了相关的网址数据。
获取到的数据中rows的形式如下
[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3…),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3…)]
列表的每个元素是一个元组,每个元素的内容是urlid和每个关键词在该文档中的位置。

wordids形式为[wordid1, wordid2, wordid3…],即每个关键词所对应的单词id

我们将会介绍几种排名算法,所谓排名也就是根据各自的规则为每个链接评分,评分越好。并且最终我们会将几种排名算法综合利用起来,给出最终的排名。既然要综合利用,那么我们就要先实现每种算法。在综合利用时会遇到几个问题。

1、每种排名算法评分机制不同,给出的评分尺度和含义也不尽相同
2、如何综合利用,要考虑每种算法的效果。为效果好的给与较大的权重。

我们先来考虑第一个问题,如何消除每种评分算法所给出的评分尺度和含义不相同的问题。
第2个问题,等研究完所有的算法以后再来考虑。

简单,使用归一化,将每个评分值缩放到0-1上,1代表最高,0代表最低。

对爬去到的数据进行排序, 有好几种排序算法:

第1个排名算法:根据单词位置进行评分的函数

我们可以认为对用户输入的多个关键词,在文档中,这些关键词出现的位置越靠前越好。比如我们往往习惯在文章的前面添加一些摘要性、概括性的描述。

     # 根据单词位置进行评分的函数.# rows是[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3...),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3...)]def locationscore(self,rows):
​            locations=dict([(row[0],1000000) for row in rows])for row in rows:
​                loc=sum(row[1:]) #计算每个链接的单词位置总和,越小说明越靠前if loc<locations[row[0]]:  #记录每个链接最小的一种位置组合
​                    locations[row[0]]=loc
​    return self.normalizescores(locations,smallIsBetter=1)#### 
第2个排名算法:根据单词频度进行评价的函数

我们可以认为对用户输入的多个关键词,在文档中,这些关键词出现的次数越多越好。比如我们在指定主题的文章中会反复提到这个主题。

    # 根据单词频度进行评价的函数# rows是[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3...),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3...)]def frequencyscore(self,rows):counts=dict([(row[0],0) for row in rows])for row in rows: counts[row[0]]+=1   #统计每个链接出现的组合数目。 每个链接只要有一种位置组合就会保存一个元组。所以链接所拥有的组合数,能一定程度上表示单词出现的多少。return self.normalizescores(counts)
第3个排名算法:根据单词距离进行评价的函数

我们可以认为对用户输入的多个关键词,在文档中,这些关键词出现的越紧凑越好。这是因为我们更希望所有单词出现在一句话中,而不是不同的关键词出现在不同段落或语句中。

# 根据单词距离进行评价的函数。# rows是[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3...),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3...)]def distancescore(self,rows):# 如果仅查询了一个单词,则得分都一样if len(rows[0])<=2: return dict([(row[0],1.0) for row in rows])# 初始化字典,并填入一个很大的值mindistance=dict([(row[0],1000000) for row in rows])for row in rows:dist=sum([abs(row[i]-row[i-1]) for i in range(2,len(row))]) # 计算每种组合中每个单词之间的距离if dist<mindistance[row[0]]:  # 计算每个链接所有组合的距离。并为每个链接记录最小的距离mindistance[row[0]]=distreturn self.normalizescores(mindistance,smallIsBetter=1)

4 实现效果

热门主题推荐实现

在这里插入图片描述

搜索界面的实现

在这里插入图片描述

查询结果页面显示

在这里插入图片描述

查询结果分页显示

在这里插入图片描述

查询结果关键字高亮标记显示

在这里插入图片描述

4 最后

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

这篇关于挑战杯 python的搜索引擎系统设计与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/716001

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详