站內搜索,能夠認爲是針對一個網站特性內容的搜索功能。因爲內容、格式可控,站內搜索比全網搜索的實現要簡單不少。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索引發來,根據狀況插入搜索結果中就好了。
本文發佈於樂天的開發筆記-掘金,同時發佈於樂天筆記。