手把手教你使用Flask搭建ES搜索引擎(预备篇)

/1 前言/

    Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。

手把手教你使用Flask搭建ES搜索引擎(预备篇)

    那么如何实现 elasticsearch和 python  的对接成为我们所关心的问题了 (怎么什么都要和 python 关联啊)。

/2 Python 交互/

所以,Python 也就提供了可以对接 Elasticsearch的依赖库。

pip install elasticsearch

登录后复制

初始化连接一个 Elasticsearch  操作对象。

def __init__(self, index_type: str, index_name: str, ip="127.0.0.1"):    # self.es = Elasticsearch([ip], http_auth=('username', 'password'), port=9200)    self.es = Elasticsearch("localhost:9200")    self.index_type = index_type    self.index_name = index_name

登录后复制

默认端口 9200,初始化前请确保本地已搭建好 Elasticsearch的所属环境。

根据 ID 获取文档数据

def get_doc(self, uid):    return self.es.get(index=self.index_name, id=uid)

登录后复制

插入文档数据

def insert_one(self, doc: dict):    self.es.index(index=self.index_name, doc_type=self.index_type, body=doc)def insert_array(self, docs: list):    for doc in docs:        self.es.index(index=self.index_name, doc_type=self.index_type, body=doc)

登录后复制

搜索文档数据

def search(self, query, count: int = 30):    dsl = {        "query": {            "multi_match": {                "query": query,                "fields": ["title", "content", "link"]            }        },        "highlight": {            "fields": {                "title": {}            }        }    }    match_data = self.es.search(index=self.index_name, body=dsl, size=count)    return match_datadef __search(self, query: dict, count: int = 20): # count: 返回的数据大小    results = []    params = {        'size': count    }    match_data = self.es.search(index=self.index_name, body=query, params=params)    for hit in match_data['hits']['hits']:        results.append(hit['_source'])    return results

登录后复制

删除文档数据

def delete_index(self):    try:        self.es.indices.delete(index=self.index_name)    except:        pass

登录后复制

好啊,封装 search 类也是为了方便调用,整体贴一下。

from elasticsearch import Elasticsearchclass elasticSearch():    def __init__(self, index_type: str, index_name: str, ip="127.0.0.1"):        # self.es = Elasticsearch([ip], http_auth=('elastic', 'password'), port=9200)        self.es = Elasticsearch("localhost:9200")        self.index_type = index_type        self.index_name = index_name    def create_index(self):        if self.es.indices.exists(index=self.index_name) is True:            self.es.indices.delete(index=self.index_name)        self.es.indices.create(index=self.index_name, ignore=400)    def delete_index(self):        try:            self.es.indices.delete(index=self.index_name)        except:            pass    def get_doc(self, uid):        return self.es.get(index=self.index_name, id=uid)    def insert_one(self, doc: dict):        self.es.index(index=self.index_name, doc_type=self.index_type, body=doc)    def insert_array(self, docs: list):        for doc in docs:            self.es.index(index=self.index_name, doc_type=self.index_type, body=doc)    def search(self, query, count: int = 30):        dsl = {            "query": {                "multi_match": {                    "query": query,                    "fields": ["title", "content", "link"]                }            },            "highlight": {                "fields": {                    "title": {}                }            }        }        match_data = self.es.search(index=self.index_name, body=dsl, size=count)        return match_data

登录后复制

尝试一下把 Mongodb 中的数据插入到 ES 中。

import jsonfrom datetime import datetimeimport pymongofrom app.elasticsearchClass import elasticSearchclient = pymongo.MongoClient('127.0.0.1', 27017)db = client['spider']sheet = db.get_collection('Spider').find({}, {'_id': 0, })es = elasticSearch(index_type="spider_data",index_name="spider")es.create_index()for i in sheet:    data = {            'title': i["title"],            'content':i["data"],            'link': i["link"],            'create_time':datetime.now()        }    es.insert_one(doc=data)

登录后复制

到 ES 中查看一下,启动 elasticsearch-head 插件。

如果是 npm 安装的那么 cd 到根目录之后直接 npm run start 就跑起来了。

本地访问  http://localhost:9100/

手把手教你使用Flask搭建ES搜索引擎(预备篇)

发现新加的 spider 数据文档确实已经进去了。

/3 爬虫入库/

要想实现 ES 搜索,首先要有数据支持,而海量的数据往往来自爬虫。

为了节省时间,编写一个最简单的爬虫,抓取 百度百科。

简单粗暴一点,先 递归获取 很多很多的 url 链接

import requestsimport reimport timeexist_urls = []headers = {    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36',}def get_link(url):    try:        response = requests.get(url=url, headers=headers)        response.encoding = 'UTF-8'        html = response.text        link_lists = re.findall('.*?]*?)".*?', html)        return link_lists    except Exception as e:        pass    finally:        exist_urls.append(url)# 当爬取深度小于10层时,递归调用主函数,继续爬取第二层的所有链接def main(start_url, depth=1):    link_lists = get_link(start_url)    if link_lists:        unique_lists = list(set(link_lists) - set(exist_urls))        for unique_url in unique_lists:            unique_url = 'https://baike.baidu.com/item/' + unique_url            with open('url.txt', 'a+') as f:                f.write(unique_url + '')                f.close()        if depth 

登录后复制

把全部 url 存到 url.txt 文件中之后,然后启动任务。

# parse.pyfrom celery import Celeryimport requestsfrom lxml import etreeimport pymongoapp = Celery('tasks', broker='redis://localhost:6379/2')client = pymongo.MongoClient('localhost',27017)db = client['baike']@app.taskdef get_url(link):    item = {}    headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36'}    res = requests.get(link,headers=headers)    res.encoding = 'UTF-8'    doc = etree.HTML(res.text)    content = doc.xpath("//div[@class='lemma-summary']/div[@class='para']//text()")    print(res.status_code)    print(link,'','++++++++++++++++++++')    item['link'] = link    data = ''.join(content).replace(' ', '').replace('', '').replace('', '').replace('', '')    item['data'] = data    if db['Baike'].insert(dict(item)):        print("is OK ...")    else:        print('Fail')

登录后复制

run.py 飞起来

from parse import get_urldef main(url):    result = get_url.delay(url)    return resultdef run():    with open('./url.txt', 'r') as f:        for url in f.readlines():            main(url.strip(''))if __name__ == '__main__':    run()

登录后复制

黑窗口键入

celery -A parse worker -l info -P gevent -c 10

登录后复制

哦豁 !!   你居然使用了 Celery 任务队列,gevent 模式,-c 就是10个线程刷刷刷就干起来了,速度杠杠的 !!

啥?分布式? 那就加多几台机器啦,直接把代码拷贝到目标服务器,通过 redis 共享队列协同多机抓取。

这里是先将数据存储到了 MongoDB 上(个人习惯),你也可以直接存到 ES 中,但是单条单条的插入速度堪忧(接下来会讲到优化,哈哈)。

使用前面的例子将 Mongo 中的数据批量导入到 ES 中,OK !!!

手把手教你使用Flask搭建ES搜索引擎(预备篇)

到这一个简单的数据抓取就已经完毕了。

好啦,现在 ES 中已经有了数据啦,接下来就应该是 Flask web 的操作啦,当然,Django,FastAPI 也很优秀。嘿嘿,你喜欢 !!

关于FastAPI 的文章可以看这个系列文章:

1、(入门篇)简析Python web框架FastAPI——一个比Flask和Tornada更高性能的API 框架

2、(进阶篇)Python web框架FastAPI——一个比Flask和Tornada更高性能的API 框架

3、(完结篇)Python web框架FastAPI——一个比Flask和Tornada更高性能的API 框架

/4 Flask 项目结构/

手把手教你使用Flask搭建ES搜索引擎(预备篇)

这样一来前期工作就差不多了,接下来剩下的工作主要集中于 Flask 的实际开发中,蓄力中 !!

以上就是手把手教你使用Flask搭建ES搜索引擎(预备篇)的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2229944.html

(0)
上一篇 2025年2月26日 14:14:02
下一篇 2025年2月26日 14:14:32

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论