All Projects → GINK03 → minimal-search-engine

GINK03 / minimal-search-engine

Licence: other
最小のサーチエンジン/PageRank/tf-idf

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to minimal-search-engine

devsearch
A web search engine built with Python which uses TF-IDF and PageRank to sort search results.
Stars: ✭ 52 (+188.89%)
Mutual labels:  search-engine, pagerank, tf-idf
iresearch
IResearch is a cross-platform, high-performance document oriented search engine library written entirely in C++ with the focus on a pluggability of different ranking/similarity models
Stars: ✭ 121 (+572.22%)
Mutual labels:  search-engine, tf-idf
Dot Hugo Documentation Theme
Dot - Hugo Documentation Theme
Stars: ✭ 162 (+800%)
Mutual labels:  search-engine, minimal
graphframes
R Interface for GraphFrames
Stars: ✭ 36 (+100%)
Mutual labels:  pagerank
Gesko
Gesko is a simple and minimalistic jekyll blogging theme.
Stars: ✭ 147 (+716.67%)
Mutual labels:  minimal
plyr
A hyperminimal, lightweight macOS desktop music application
Stars: ✭ 48 (+166.67%)
Mutual labels:  minimal
mini i18n
🌐 Minimalistic I18n library for Ruby
Stars: ✭ 93 (+416.67%)
Mutual labels:  minimal
jack bunny
Inspired by Facebook's bunnylol search engine.
Stars: ✭ 19 (+5.56%)
Mutual labels:  search-engine
seo-analyzer
The library for analyze a HTML file to show all of the SEO defects
Stars: ✭ 53 (+194.44%)
Mutual labels:  search-engine
NLP-paper
🎨 🎨NLP 自然语言处理教程 🎨🎨 https://dataxujing.github.io/NLP-paper/
Stars: ✭ 23 (+27.78%)
Mutual labels:  pagerank
pia
📚 🔬 PIA - Protein Inference Algorithms
Stars: ✭ 19 (+5.56%)
Mutual labels:  search-engine
fleeg-platform
Fleeg is a free and open source platform to index and search pages.
Stars: ✭ 21 (+16.67%)
Mutual labels:  search-engine
revery
A personal semantic search engine capable of surfacing relevant bookmarks, journal entries, notes, blogs, contacts, and more, built on an efficient document embedding algorithm and Monocle's personal search index.
Stars: ✭ 200 (+1011.11%)
Mutual labels:  search-engine
react-search
This package will help you create a pretty good and beautiful search. And other related features
Stars: ✭ 17 (-5.56%)
Mutual labels:  search-engine
text-classification-cn
中文文本分类实践,基于搜狗新闻语料库,采用传统机器学习方法以及预训练模型等方法
Stars: ✭ 81 (+350%)
Mutual labels:  tf-idf
creators-code
A minimal alternative for other codes of conduct I have seen.
Stars: ✭ 46 (+155.56%)
Mutual labels:  minimal
h.js
2KB JavaScript Syntax Highlighter
Stars: ✭ 37 (+105.56%)
Mutual labels:  minimal
torrent-hound
Search torrents from multiple websites via the CLI
Stars: ✭ 28 (+55.56%)
Mutual labels:  search-engine
hyper-rose-pine-next
Hyper Theme - which supports your System Preferences
Stars: ✭ 28 (+55.56%)
Mutual labels:  minimal
ByteCopy
Simple C99 program and API for copying files.
Stars: ✭ 16 (-11.11%)
Mutual labels:  minimal

依存パッケージと依存ソフトウェア

GitHubのコードを参照してください [https://github.com/GINK03/minimal-search-engine:embed]

様々なサイトを巡回する必要があり、requestsが文字コードの推論を高確率で失敗するので、nkf をlinux環境で入れている必要があります。

$ sudo apt install nkf
$ which nkf
/usr/bin/nkf

Mecabも入れます

$ sudo apt install mecab libmecab-dev mecab-ipadic
$ sudo apt install mecab-ipadic-utf8
$ sudo apt install python-mecab
$ pip3 install mecab-python3
$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ ./bin/install-mecab-ipadic-neologd -n

残りの依存をインストールします

$ pip3 install -r requirements.txt

再現

基本的にGitHubのコードをUbuntu等のLinuxでAから順に実行してもらえば、再現できます。

クローラ(スクレイパー)はやろうと思えば無限に取得してしまうので、適当にSEEDを決めて、適当な時間で終了することを前提としていています。

全体の処理の流れ

A. クローリング
B. クローリングしたHTMLを, title, description, body, hrefsをパースしデータを整形する
C. IDF辞書の作成
D. TFIDFのデータを作成
F. 転置したurl, hrefの対応を作成(単純な被参照量の特徴量)
G. 非参照数のカウントと、PageRankのための学習データの作成
H. URLとtfidfのウェイトの転置インデックスを作成
I. hash化されたURLと実際のURLの対応表の作成
J. PageRankの学習
K. 検索のインターフェース

プログラムの詳細

A. クローリング

特定のドメインによらず、網羅的にクローリングしていきます。 ブログサイトをシードとしてドメインを限定せずどこまでも深く潜っていきます。
多様なサイトをクロールするがとても重いので、自作した分散可能なKVSをバックエンドのDBと利用しています。SQLLiteなどだとファイルが壊れやすく、LevelDB等だとシングルアクセスしかできません。

B. HTMLのパースと整形

Aで取得したデータは大きすぎるので、Bのプロセスで、tfidfでの検索の主な特徴量となる、"title", "description", "body"を取り出します。
また、そのページが参照している外部のURLをすべてパースします。

soup = BeautifulSoup(html, features='lxml')
for script in soup(['script', 'style']):
    script.decompose()
title = soup.title.text
description = soup.find('head').find(
                'meta', {'name': 'description'})
if description is None:
    description = ''
else:
    description = description.get('content')
body = soup.find('body').get_text()
body = re.sub('\n', ' ', body)
body = re.sub(r'\s{1,}', ' ', body)

BeautifulSoupでシンプルに処理することができる.

C. IDF辞書の作成

頻出する単語の重要度を下げるために、各単語がどの程度のドキュメントで参照されているかをカウントします。

D. TDIDFの計算

B, Cのデータを利用して、TFIDFとして完成させます
title description bodyはそれぞれ重要度が異なっており、 title : description : body = 1 : 1 : 0.001
として処理しました。

# title desc weight = 1
text = arow.title + arow.description 
text = sanitize(text)
for term in m.parse(text).strip().split():
    if term_freq.get(term) is None:
        term_freq[term] = 0
    term_freq[term] += 1

# title body = 0.001 
text = arow.body
text = sanitize(text)
for term in m.parse(text).strip().split():
    if term_freq.get(term) is None:
        term_freq[term] = 0
    term_freq[term] += 0.001 # ここのweightを 0.001 のように小さい値を設定する

F. あるURLと、あるURLのHTMLがリンクしているURLの転置インデックスを作成

昔良くあった、URLのリンクを色んな所から与えるとSEOができるということを知っていたので、どの程度外部から被参照されているか知るため、このような処理を行います

G. 被参照数のカウントと、PageRankのための学習データの作成

Fで作成したデータをもとに、networkxというライブラリでPageRankのノードのウェイトを学習可能なので、学習用データを作成します

このようなデータセットが入力として望まれます(右のハッシュがリンク元、左のハッシュがリンク先)

d2a88da0ca550a8b 37a3d49657247e61
d2a88da0ca550a8b 6552c5a8ff9b2470
d2a88da0ca550a8b 3bf8e875fc951502
d2a88da0ca550a8b 935b17a90f5fb652
7996001a6e079a31 aabef32c9c8c4c13
d2a88da0ca550a8b e710f0bdab0ac500
d2a88da0ca550a8b a4bcfc4597f138c7
4cd5e7e2c81108be 7de6859b50d1eed2

H. 単語から簡単にURLを逆引きできるように、転置インデックスの作成

最もシンプルな単語のみでの検索に対応できるように、単語からURLをすぐ検索できるindexを作ります
出力が、単語(のハッシュ値)ごとにテキストファイルが作成されて、 URLのハッシュ , weight(tfidf) , refnum(被参照数) のファイルが具体的な転置インデックスのファイルになります

0010c40c7ed2c240        0.000029752     4
000ca0244339eb34        0.000029773     0
0017a9b7d83f5d24        0.000029763     0
00163826057db7c3        0.000029773     0

I. URLとhash値の対応表の作成

URLはそのままメモリ上に持つとオーバーフローしてしまうので、sha256をつかって先頭の16文字だけを使った小さいhash値とみなすことで100万オーダーのドキュメントであってもある程度実用に耐えうる検索が可能になります。

J. PageRankの学習

Gで作成したデータを学習してURLにPageRankの値を学習します。

networkxを用いれば凄くシンプルなコードで学習する事ができます

import networkx as nx
import json
G = nx.read_edgelist('tmp/to_pagerank.txt', nodetype=str)
# ノード数とエッジ数を出力
print(nx.number_of_nodes(G))
print(nx.number_of_edges(G))
print('start calc pagerank')
pagerank = nx.pagerank(G)
print('finish calc pagerank')
json.dump(pagerank, fp=open('tmp/pagerank.json', 'w'), indent=2)

K. 検索のインターフェース

検索IFを提供

$ python3 K001_search_query.py
(ここで検索クエリを入力)

$ python3 K001_search_query.py
ふわふわ
                   hurl    weight  refnum  weight_norm                                                            url  pagerank  weight*refnum_score+pagerank
9276   36b736bccbbb95f2  0.000049       1     1.000000  https://bookwalker.jp/dea270c399-d1c5-470e-98bd-af9ba8d8464a/  0.000146                      1.009695
2783   108a6facdef1cf64  0.000037       0     0.758035     http://blog.livedoor.jp/usausa_life/archives/79482577.html  1.000000                      0.995498
32712  c3ed3d4afd05fc43  0.000045       1     0.931093          https://item.fril.jp/bc7ae485a59de01d6ad428ee19671dfa  0.000038                      0.940083
...

実際の使用例

"雷ちゃん"等で検索すると、ほしい情報がおおよそちゃんと上に来るようにチューニングすることができました。
Pixivについては明示的にクローリング先に設定していないが、Aのクローラがどんどんとリンクをたどりインデックスを作成した結果で、自動で獲得したものです。

"洒落怖"など、他のクエリでも望んだ結果が帰ってきています。

検索のスコアリングはどうあるべきか

手でいろいろ試してみて、良さそうなスコアはこのような感じなりました。(私が正解データです)

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].