基于Python的搜索引擎实现
文章目录
前言
随着互联网和宽带上网的普及, 搜索引擎在中国异军突起, 并日益渗透到人们的日常生活中, 在互联网普及之前, 人们查阅资料首先想到的是拥有大量书籍的资料的图书馆。 但是今天很多人都会选择一种更方便、 快捷、 全面、 准确的查阅方式–互联网。 而帮助我们在整个互联网上快速地查找到目标信息的就是越来越被重视的搜索引擎。
今天学长来向大家介绍如何使用python写一个搜索引擎,该项目常用于毕业设计
1.实现
1.1 系统架构
搜索引擎有基本的五大模块,分别是:
- 信息采集模块
- 信息处理模块
- 建立索引模块
- 查询和 web 交互模块
本设计研究的是如何在信息处理分析的基础上,建立一个完整的中文搜索引擎。
所以该系统主要由以下几个详细部分组成:
- 爬取数据
- 中文分词
- 相关度排序
- 建立web交互。
1.2 爬取大量网页数据
爬取数据,实际上用的就是爬虫。
我们平时在浏览网页的时候,在浏览器里输入一个网址,然后敲击回车,我们就会看到网站的一些页面,那么这个过程实际上就是这个浏览器请求了一些服务器然后获取到了一些服务器的网页资源,然后我们看到了这个网页。
请求呢就是用程序来实现上面的过程,就需要写代码来模拟这个浏览器向服务器发起请求,然后获取这些网页资源。那么一般来说实际上获取的这些网页资源是一串HTML代码,这里面包含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.do
if __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"] = chromedriver
browser = 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_source
travel_name = browser.find_element_by_xpath('//*[@id="layer213"]').text
titles.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()
1.3 中文分词
中文分词使用jieba库即可
jieba 是一个基于Python的中文分词工具对于一长段文字,其分词原理大体可分为三步:
1.首先用正则表达式将中文段落粗略的分成一个个句子。
2.将每个句子构造成有向无环图,之后寻找最佳切分方案。
3.最后对于连续的单字,采用HMM模型将其再次划分。
jieba分词分为“默认模式”(cut_all=False),“全模式”(cut_all=True)以及搜索引擎模式。对于“默认模式”,又可以选择是否使用 HMM 模型(HMM=True,HMM=False)。
1.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]]=dist
return self.normalizescores(mindistance,smallIsBetter=1)
1.5 建立web交互
使用任何前端技术都可以完成
我使用html做的,效果如下:
最后
如何获取项目帮助和源码、
本文地址:https://blog.csdn.net/HUXINY/article/details/109784221