•  

【20201021】做个搜索引擎(9)——搜索器

发表于 2020-10-19,阅读 13

介绍

介绍

今天开始我们要做搜索引擎的“界面”部分了,我们给这个工具起个名字——搜索器,因为我们使用的是Python编写的搜索器,所以我们的搜索器是控制台形式的。

搜索器的名称是Searcher,搜索器的启动程序文件名称是Searcher.py,搜索器包含一个库文件lib/Searcher.py。

搜索器的功能是这样的,启动搜索器Searcher.py,提示用户输入一个关键字,用户输入关键字后查询ES搜索引擎,给出最多10个匹配记录的网页标题以及1~10个序号,并且自动转入下一轮的搜索提示信息。

Searcher对象

搜索引擎的界面的代码逻辑相对比较简单,福哥就在今天一节课里把它发出来,并且给童鞋们讲解清楚。

代码

这是Searcher对象的代码,保存在 lib/Searcher.py 里面,作为一个自定义软件包使用。

import pymysql
from elasticsearch import Elasticsearch

class Searcher:
    args = None
    mysqlCN = None
    mysqlCS = None
    es = None

    def __init__(self, args):
        self.args = args

    def open(self):
        try:
            self.mysqlCN = pymysql.connect(host=self.args["dbstathost"],port=self.args["dbstatport"],user=self.args["dbstatuser"],password=self.args["dbstatpwd"])
            self.mysqlCS = self.mysqlCN.cursor()
            self.mysqlCN.select_db(self.args["dbstatdb"])
        except Exception as e:
            print e
            exit()
            
        try:
            self.es = Elasticsearch(host=self.args["eshost"], port=self.args["esport"], timeout=self.args["estimeout"])
        except Exception as e:
            print e
            exit()

    def search(self, kw):
        try:
            query = {
                "from": 0,
                "size": 10,
                "query":{
                    "bool":{
                        "must":[
                            {
                                "bool":{
                                    "should":[
                                        {"match":{"title":{
                                                "query": kw,
                                                "boost": 25
                                            }}},
                                        {"match":{"keywords":{
                                                "query": kw,
                                                "boost": 20
                                            }}},
                                        {"match":{"description":{
                                                "query": kw,
                                                "boost": 10
                                            }}},
                                        {"match":{"pageText":{
                                                "query": kw,
                                                "boost": 1
                                            }}}
                                    ]
                                }
                            }
                        ]
                    }
                }
            }
            results = self.es.search(index=self.args["esindex"],doc_type=self.args["esdoctype"],body=query)
            if results['hits']['total'] > 0:
                print ("查询到" + str(results['hits']['total']) + "个结果")
                print ("")
                num = 1
                for result in results['hits']['hits']:
                    try:
                        self.mysqlCS.execute("SELECT * FROM webpages WHERE webpageId = %s", [result['_source']['webpageid']])
                        row = self.mysqlCS.fetchone()
                        print (str(num) + " " + row[5].decode("utf-8").encode("gbk"))
                        print ("  " + row[2])
                    except Exception as e2:
                        doNothing = e2
                    num = num+1
            else:
                print ("未找到符合“" + kw + "”的结果")
        except Exception as e:
            print e #doNothing = e

    def close(self):
        try:
            self.es.close()
        except Exception as e:
            print e
            exit()

主程序

这里是搜索引擎界面的主程序,主程序通过上面的Searcher对象实现网页搜索的功能,保存在 Searcher.py 里面。

from lib.Searcher import *
import sys

mySearcher = Searcher({
    "dbstathost": "192.168.1.113",
    "dbstatport": 3306,
    "dbstatuser": "tfse",
    "dbstatpwd": "abcdef",
    "dbstatdb": "tfse",
    
    "eshost": "192.168.1.113",
    "esport": 9200,
    "estimeout": 60,
    "esindex": "tfse",
    "esdoctype": "all_type"
})
mySearcher.open()

while 1:
    print ("请输入关键字: "),
    kw = sys.stdin.readline().strip()

    print ("")
    mySearcher.search(kw)
    print ("")

mySearcher.close()

讲解

下面福哥来讲解一下这个代码的逻辑,大家可以跟着福哥的思路一起读这段代码,了解其中的设计和功能。

主程序

主程序比较简单,启动一个“死循环”的while循环语句,在循环语句里面首先要求用户输入一个搜索关键字,然后将这个关键字传入Searcher对象的search方法里进行全文搜索,search方法会将搜索结果显示出来给用户看

Searcher对象

接着福哥来介绍一下Searcher对象的每个方法,大家可以了解一下。

open

搜索引擎需要同时连接mysql数据库和es搜索引擎,在open方法里面会对mysql和es进行连接和初始化操作

search

这个方法是搜索引擎的主逻辑方法,传入参数是用户的搜索关键字,程序会通过用户关键字查询es搜索引擎,并将结果遍历出来,在循环的过程中通过es数据的webpageid字段查询mysql数据库的webpages数据表对应的记录,最后将mysql数据库里的数据显示到用户面前

close

在这个方法里面会将mysql数据库和es搜索引擎关闭掉以释放资源

输出

执行主程序会提示输入搜索关键字,输入关键字后会根据搜索结果显示匹配项目

928e68b688abdb59.jpg

总结

到今天为止,我们的搜索引擎第一版就做好了,大家学会了吗?

这个搜索引擎是福哥带着童鞋们做的第一个项目,它用到了MySQL数据库和ElasticSearch搜索引擎,它包括两个部分,即:网页蜘蛛和搜索界面,网页蜘蛛负责数据的“写入”,搜索界面负责数据的“读取”。这个项目还用到了OOP对象编程思维进行代码的结构设计,网页蜘蛛封装为Spider对象,搜索界面封装为Searcher对象。

大家可能会问,为什么Spider对象和Searcher对象不和Spider主程序和Searcher主程序放一起了?注意,写程序要有分层思维,即:功能实现和业务逻辑的分离,不要在业务逻辑的代码里面去实现功能,也不要在功能代码里去编写业务逻辑的代码,这样才不会把代码写的乱七八糟的,也便于今后的功能升级改造。

P.S.

微信公众号的文章发出去之后是不能编辑的,但是福哥偶尔会修复一些描述不到位、示例不正确、结构不清晰等等的文章错误,这些只能在网站上才能看到最新版本内容,望大家知晓~~


鬼谷子叔叔
  • 日志:212
  • 回复:13

进入ta的主页