那些年,我爬过的北科(十)——搜索案例之ElasticSearch的使用

为何要用ElasticSearch?

通常来讲数据库都会自带模糊搜索的功能,但其实上真正使用的时候,遇到中文搜索这种问题时,搜索速度会很是慢,可能会须要O(n)或者O(logn)的复杂度。html

在实际使用中,这是不容许的,由于用户就搜索一条语句。假设n很是大的话,等待时间可能会很是的久。因此确定须要使用索引机制,加速搜索效率。java

搜索引擎使用的是倒排索引,创建好索引后,能够在O(c)的时间完成搜索功能。不过这步只是一个粗略的查询,还要对搜索的结果进行排序,这里可能会用到如BM25Query Likelihood Model等给文档打分的方法,经过打分对搜索结果进行排序。python

若是咱们本身去实现这些功能的话,首先可能要学学什么是倒排索引,还有文档的打分的各类方法,再加上代码,要用起来不知道要到哪年哪月了。而ElasticSearch将这些操做变得很是简单。它是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。git

下面咱们将要讲解如何使用ElasticSearch构建咱们的帖子搜索。github

ElasticSearch安装

“工欲善其事,必先利其器”,咱们这里先讲解一些ElasticSearch的安装步骤,下面的操做是在mac系统上进行的。由于ElasticSearch是基于Java开发的,Java自己是跨平台的,因此其余系统上面其实操做都是基本同样的。web

ElasticSearch安装

这里首先安装JDK,而后下载安装ElasticSearch-6.0.0版本。算法

下载解压后,咱们能够看到这里有一个bin文件夹。mongodb

bin文件夹里都是ElasticSearch相关操做的脚本。咱们把ElasticSearch的bin目录添加到PATH中,以后在终端中就不须要输入绝对路径了。数据库

export PATH=$HOME/ProgramFiles/elasticsearch-6.0.0/bin:${PATH}
复制代码

ik分词工具的安装

由于咱们作的是中文搜索,而ElasticSearch自带的中文分词作的很差,因此这里须要使用到ik的一个插件。使用如下命令安装便可。bash

elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.0.0/elasticsearch-analysis-ik-6.0.0.zip
复制代码

Python库的安装

最后,咱们由于要使用python操做ElasticSearch,经过pip命令安装ElasticSearch的API库。

pip install elasticsearch
复制代码

服务启动

在创建索引以前,咱们要先打开ElasticSearch服务。在终端输入elasticsearch命令便可。

启动后能够看到ElasticSearch服务监听了本地的9300端口。

索引构建

接下来,咱们来看看如何创建索引。

建立Mappings

首先像数据库同样,咱们先创建一个索引。这里咱们管它叫:tiezi_index。在建立索引的过程当中,要配置映射一个Mappings(映射)。

咱们先来看下代码:

from elasticsearch import Elasticsearch

es = Elasticsearch()

# 初始化索引的Mappings设置,只有一个字段: 标题。
index_mappings = {
  "mappings": {
    "tiezi": {
      "properties": {
        "title": {
            "type": "text",
            "analyzer": "ik_max_word",
            "search_analyzer": "ik_max_word"
        },
      }
    },
  }
}

if es.indices.exists(index='tieba_index') is not True:
    print("create tieba_index")
    es.indices.create(index='tieba_index', body=index_mappings)
复制代码

这里主要看一下index_mappings这个变量,在Mappings下面是一个Type(类型),这里Type的名称我起名为:tiezi。Type其实就相似于mongodb中集合的概念,是对文档分区的。

对于tiezi这个类型,还要配置一下它所包含的属性。因为咱们的帖子只爬取了标题,因此只有一个title就行了。

能够看到在title字段里面还有东西,这里指定了title是文本类型,而且使用ik分词工具进行分析索引。

索引数据

完成映射后,咱们开始把全部数据进行索引。这里只须要遍历一遍咱们爬的帖子数据,而后索引到ElasticSearch里就行了。

def init_collection():
    client = pymongo.MongoClient(host="localhost", port=27017)
    db = client['tieba']
    return db["beike"]

coll = init_collection()

for tiezi in coll.find():
    _id = str(tiezi["_id"])
    doc = {
        "id": _id,
        "title": tiezi["title"]
    }
    print(doc)
    res = es.index(index="tieba_index", doc_type="tiezi", id=_id, body=doc)
    print(res)
复制代码

这里索引须要花必定的时间,耐心等待便可。

搜索测试

最后,咱们进行一下搜索测试。搜索直接能够调用search便可。搜索的返回结果是字典类型。

from elasticsearch import Elasticsearch


def search(query):
    query_contains = {
        'query': {
            'match': {
                'title': query,
            }
        }
    }
    es = Elasticsearch()
    searched = es.search("tieba_index", doc_type="tiezi", body=query_contains, size=20)

    return searched


for res in search("假期都作什么呢")["hits"]["hits"]:
    print(res["_source"]["title"], res["_score"])
复制代码

咱们这里能够打印一下,搜索出来的标题和搜索的得分(默认是BM25得分)。

结束语

到这里,本系列教程的全部内容都结束了。网络爬虫是一个很是实践的应用,在真正爬取数据时,可能会遇到各类各样的问题。从数据存储、反反爬虫以及算法上可能都要踩不少坑。

本系列教程力求可以从浅入深的讲解网络爬虫,尽量覆盖到爬虫所涉及的内容的方方面。固然有些部分也会比较粗糙,只是大概提了一句。但愿经过本系统教程,能让读者可以对爬虫有一个宏观的认识与了解。

相关文章
相关标签/搜索