站内搜索,能够认为是针对一个网站特性内容的搜索功能。因为内容、格式可控,站内搜索比全网搜索的实现要简单不少。html
简书这个网站自己自带一个搜索,可是缺少针对我的文章的搜索,因此本文的实战内容是解决这个痛点。python
代码在 github.com/letiantian/…,可使用下面的方式把代码下载下来查看:git
git clone https://github.com/letiantian/jianshu-site-search.git
复制代码
代码在Python2.7下运行。须要安装如下依赖:github
pip install elasticsearch==6.0.0 --user
pip install uniout --user
pip install requests --user
pip install beautifulsoup4 --user
pip install Django --user
复制代码
若是是简书给本身作我的搜索,从数据库里拿就好了。web
我这种状况,天然用爬虫抓取。数据库
抓取某我的全部的文章,最终是URL
、标题
、正文
三个部分。浏览器
以www.jianshu.com/u/7fe2e7bb7…这个(随便找的)用户主页为例。7fe2e7bb7d47
能够认为是这个用户的ID。 文章地址相似http://www.jianshu.com/p/9c2fdb9fa5d1
,9c2fdb9fa5d1
是文章 ID。bash
通过分析,能够以此请求下面的地址,从中解析出文章地址,获得地址集合:elasticsearch
http://www.jianshu.com/u/7fe2e7bb7d47?order_by=shared_at&page=1
http://www.jianshu.com/u/7fe2e7bb7d47?order_by=shared_at&page=2
http://www.jianshu.com/u/7fe2e7bb7d47?order_by=shared_at&page=3
// ... page的值不断增长
// ... 当page不存在的时候,简书会返回page=1的内容,这时候中止抓取
复制代码
而后,依次抓取文章内容,保存下来。分布式
crawler.py 用于抓取文章,使用方法:
python crawler.py 7fe2e7bb7d47
复制代码
文章对应的网页会保存到data
目录,用文章ID命名。
对于每一个搜索词查看每一个文章的标题和正文中有无该词:
一篇文章命中的搜索词越多,分值越高。
将结果排序输出便可。
代码实如今simple_search.py ,使用方法:
$ python simple_search.py 人民 名义
你输入了: 人民 名义
搜索结果:
url: http://www.jianshu.com/p/6659d5fc5503
title: 《人民的名义》走红的背后 文化产业投资难以言说的痛
score: 6
url: http://www.jianshu.com/p/ee594ea42815
title: LP由《人民的名义》反思 GP投资权力真空怎么破
score: 6
url: http://www.jianshu.com/p/4ef650769f73
title: 弘道资本:投资人人贷、ofo 人民币基金逆袭的中国样本
score: 3
复制代码
这种方法的缺点是:
Elasticsearch 是一个通用的搜索引擎解决方案,提供了优雅的 HTTP Restful 接口、丰富的官方文档。 阮一峰为它写了一份简明易懂的教程:全文搜索引擎 Elasticsearch 入门教程,推荐阅读。
Elasticsearch 基本原理:
咱们先搭建环境:
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.0.0/elasticsearch-analysis-ik-6.0.0.zip
复制代码
或者下载下来解压到Elasticsearch的plugins目录。 4. 启动:
./bin/elasticsearch
复制代码
环境搭建完成。
python es_create_index.py
复制代码
建立时指定了分词器。
python es_index_data.py
复制代码
为了防止一篇文章被重复索引,添加索引时 Document ID 设置为文章 ID。
python es_search.py 人民的名义
复制代码
高亮搜索结果:
python es_hl_search.py 人民的名义
复制代码
基于Django实现了一个简单的web界面。运行:
python webui/manage.py runserver
复制代码
浏览器访问http://127.0.0.1:8000/
便可。体验效果:
中止词是很是常见的单词,例如的
、the
等。通常用法是在分词后去掉中止词,而后进行索引。这种作法的常见理由是减小索引大小。同时,从理论上看,也能够提高检索速度。 相应的,这里有两个问题须要探讨:
是否能达到业务的需求才是目标。若是须要在搜索的
这个词的时候有结果,那么上面的作法就是不合理的。
我更倾向于底层索引不启用中止词,而是根据业务需求在业务层进行必要的中止词处理。
要Elasticsearch返回搜索结果的第10001条到第10010条数据,是一个耗时的操做,由于Elasticsearch要先获得打分最高的前10010条数据,而后从中取出第10001条到第10010条数据。
用户感知到的搜索界面是分页的,每页是固定数量的数据(如10条),用户会跳转到第1001页的搜索结果吗?不会。第1001页的搜索结果有意义吗?没有意义,用户应该调整搜索词。
综上,应限制用户获得的搜索结果数量。
本文的示例的数据由一个用户的全部文章组成,数据量很小。若是简书全站搜索也是用Elasticsearch,它能处理好吗?
事实上,Elasticsearch 支持分片和分布式部署,能近实时的处理海量数据。注意,索引耗时会很大,可是搜索很快。
推广内容自己也能够被Elasticsearch索引发来,根据状况插入搜索结果中就好了。
本文发布于樂天的开发笔记-掘金,同时发布于樂天笔记。