Scrapyでサイトをクロールし、ElasticSearchでサイトの概要を把握する (3)

前回までで、Scrapyでクロールしたページ情報をElasticSearchにインデックスするところまで設定したが、
実はあれだけだと、うまくESやkibana上で検索できなかったりする。
デフォルトではDynamic Mappingといって
データをPOSTすれば勝手にフィールドなどを作ってくれるが、url文字列をうまく扱ってくれなかったり、細かい
データ型の指定や、analyzerの指定ができない。
https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-mapping.html


なので、scrapyから送る属性をelasticsearchにマッピングしてあげる。


今回は、kibanaのdev toolを使って下記のようなマッピングを行った。

#一度インデックスを削除
DELETE scrapy-2017

#マッピングルールを設定
# - タイトルやdescriptionは日本語解析ができるように
# - URLはngramでなど
PUT scrapy-2017
{
  "settings": {
    "index": {
      "analysis": {
        "tokenizer": {
          "ja_text_tokenizer": {
            "type": "kuromoji_tokenizer",
            "mode": "search"
          },
          "ngram_tokenizer": {
            "type": "ngram",
            "min_gram": 2,
            "max_gram": 2,
            "token_chars": [
              "letter",
              "digit",
              "punctuation",
              "symbol"
            ]
          }
        },
        "analyzer": {

          "ja_text_analyzer": {
            "tokenizer": "ja_text_tokenizer",
            "type": "custom",
            "char_filter": [
              "icu_normalizer"
            ],
            "filter": [
              "kuromoji_part_of_speech"
            ]
          },
          "ngram_analyzer": {
            "tokenizer": "ngram_tokenizer"
          }
        }
      }
    }
  },
  "mappings": {
    "crawledpage": {
      "dynamic": "strict",
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "ja_text_analyzer"
        },
        "description": {
          "type": "text",
          "analyzer": "ja_text_analyzer"
        },
        "url": {
          "type": "text",
          "analyzer": "ngram_analyzer",
          "copy_to": "url_raw"
        },
        "path": {
          "type": "keyword",
          "index": "not_analyzed",
          "ignore_above": 256
        },
        "host": {
          "type": "keyword",
          "index": "not_analyzed",
          "ignore_above": 256
        }, 
        "referer": {
          "type": "text",
          "analyzer": "ngram_analyzer"
        },
        "word_count": {
          "type": "integer"
        },
        "status": {
          "type": "integer"
        }
      }
    }
  }
}

これでkibanaなどで適切に検索ができるようになった。