通常来讲数据库都会自带模糊搜索的功能,但其实上真正使用的时候,遇到中文搜索这种问题时,搜索速度会很是慢,可能会须要O(n)或者O(logn)的复杂度。html
在实际使用中,这是不容许的,由于用户就搜索一条语句。假设n很是大的话,等待时间可能会很是的久。因此确定须要使用索引机制,加速搜索效率。java
搜索引擎使用的是倒排索引
,创建好索引后,能够在O(c)的时间完成搜索功能。不过这步只是一个粗略的查询,还要对搜索的结果进行排序,这里可能会用到如BM25
、Query Likelihood Model
等给文档打分的方法,经过打分对搜索结果进行排序。python
若是咱们本身去实现这些功能的话,首先可能要学学什么是倒排索引,还有文档的打分的各类方法,再加上代码,要用起来不知道要到哪年哪月了。而ElasticSearch将这些操做变得很是简单。它是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。git
下面咱们将要讲解如何使用ElasticSearch构建咱们的帖子搜索。github
“工欲善其事,必先利其器”,咱们这里先讲解一些ElasticSearch的安装步骤,下面的操做是在mac系统上进行的。由于ElasticSearch是基于Java开发的,Java自己是跨平台的,因此其余系统上面其实操做都是基本同样的。web
这里首先安装JDK,而后下载安装ElasticSearch-6.0.0版本。算法
下载解压后,咱们能够看到这里有一个bin
文件夹。mongodb
bin
文件夹里都是ElasticSearch相关操做的脚本。咱们把ElasticSearch的bin
目录添加到PATH
中,以后在终端中就不须要输入绝对路径了。数据库
export PATH=$HOME/ProgramFiles/elasticsearch-6.0.0/bin:${PATH}
复制代码
由于咱们作的是中文搜索,而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操做ElasticSearch,经过pip命令安装ElasticSearch的API库。
pip install elasticsearch
复制代码
在创建索引以前,咱们要先打开ElasticSearch服务。在终端输入elasticsearch
命令便可。
启动后能够看到ElasticSearch服务监听了本地的9300端口。
接下来,咱们来看看如何创建索引。
首先像数据库同样,咱们先创建一个索引。这里咱们管它叫: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得分)。
到这里,本系列教程的全部内容都结束了。网络爬虫是一个很是实践的应用,在真正爬取数据时,可能会遇到各类各样的问题。从数据存储、反反爬虫以及算法上可能都要踩不少坑。
本系列教程力求可以从浅入深的讲解网络爬虫,尽量覆盖到爬虫所涉及的内容的方方面。固然有些部分也会比较粗糙,只是大概提了一句。但愿经过本系统教程,能让读者可以对爬虫有一个宏观的认识与了解。