Fessのクローラを機械学習に活用するための調査

機械学習のためのデータ収集にFessが使えるのか調査したいと思います。

Fessとは

Javaで作られApacheライセンスで提供されるオープンソース全文検索サーバです。検索エンジンとして以前はApache Solrが使われていましたが、現在ではElasticsearchが使われています。

Fessのインストール

Fessのセットアップは公式の手順で確認できます。
https://fess.codelibs.org/ja/setup.html

  • Javaのインストール
    FessではJavaの1.8以上のランタイムが必要になるので、入ってなければインストールしてJAVA_HOMEに設定を入れておきます。

  • Fessの起動
    Fessはgithubのページのreleaseからzipをダウンロードしてきます。
    https://github.com/codelibs/fess/releases
    ダウンロードしたら解答して中にある"bin/fess"を実行するとFessが立ち上がります。それからブ

ラウザで以下のURLにアクセスするとFessが起動しているのを確認できます。

http://localhost:8080/

管理者ページのURLは以下で初期ユーザのID,PASSWORDはadmin, adminとなります。

http://localhost:8080/admin/

Webクローラの設定

管理者画面にログイン後WEBクローラの設定はサイドメニューの"クローラ -> ウェブ"を表示しウェブのクロール画面で"新規作成"をクリックします。 f:id:steavevaivai:20180701181626p:plain

クロールの設定画面ではクロール対象のURLを入力します。例えばGIGAZINEをクロールする場合、URLにhttps://gigazine.net/ を入力しクロール対象のURLはhttps://gigazine.net/配下なのでhttps://gigazine.net/.* を設定します。https://gigazine.net/*ではないので気をつけます。深さはURLに設定したページからたどるページの深度になります。それから最大アクセス数は一度のクロールでアクセスする最大ページ数になります、間隔はクロールする感覚です。クロール対象のページには負荷をかけないように気をつけないといけません。 f:id:steavevaivai:20180701181640p:plain

それから、クロールのスケジュールは"システム -> スケジューラ"をクリックしてジョブスケジューラ画面を表示します。 f:id:steavevaivai:20180701181700p:plain
それからDefault Crawler をクリックして、スケジュールの設定を行いますデフォルトは一日1回となっています。すぐにクロールを実行したい場合はジョブの詳細画面で"今すぐ開始" をクリックします。 f:id:steavevaivai:20180701181721p:plain
クロールが実行できたらFessで検索を実行することで検索結果が表示されます。 f:id:steavevaivai:20180701181742p:plain   

それから、サイドメニューの"システム情報 -> クロール情報"から項目をクリックすることでインデックスしたサイズはクロールの開始、終了時刻を確認することができます。 f:id:steavevaivai:20180701181813p:plain
ウェブクローラは簡単に設定して動かすことができるので、自作するよりもFessを使う方が良さそうです。

クロールデータの確認

機械学習に活用できるかクロールしたデータをどう保持しているか確認したいと思います。まず、デフォルトの状態でFessを起動した場合は開発者モードとなっております(管理者画面右上の!マーククリックで確認できます)。開発者モードでは内蔵のElasticsearchが起動しておりhtmlのポートとトランスポート用のポートがそれぞれ9201と9301となっております。

Fess自身にも検索用のAPIが提供されていますが機械学習用のデータとして活用したい場合は内部でデータをどう保持しているかわかっている方が良さそうに思います。
https://fess.codelibs.org/ja/10.1/api/api-search.html

まず、インデックスの一覧を確認してみます。

$ curl -XGET http://localhost:9201/_cat/indices\?v

health status index                              uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .fess_config.request_header        1q9KJ3IQToaf-mLx5Gv0ow   1   0          0            0       261b           261b
green  open   .fess_config.failure_url           uofxuYrURNO4-AUYqgJT0Q   1   0          3            0     55.7kb         55.7kb
green  open   .fess_config.file_config           1oXJpXZ7Tke4__O2K5TgNw   1   0          0            0       261b           261b
green  open   .fess_config.boost_document_rule   f5Q442xkSwCB3VcQSqbJqw   1   0          0            0       261b           261b
green  open   .crawler.data                      PUhSo9P-QeeIUq2oARvczA   5   0          3            0     19.3kb         19.3kb
green  open   .fess_config.elevate_word          JCvV_9AaQMe6zY6UMnEefg   1   0          0            0       261b           261b
green  open   .fess_config.elevate_word_to_label jcaBPyvLTuiTdxYdCSuM_g   1   0          0            0       261b           261b
green  open   .fess_config.key_match             KP7TKaGiTZe_Mxk4lzm4_Q   1   0          0            0       261b           261b
green  open   fess_log.user_info                 O3q0yVKRQJqHmNOyEHl3Bw   5   0          1            0      4.1kb          4.1kb
green  open   .fess_config.web_config_to_role    dK2zljevSCysJ-bCL9LbaA   1   0          0            0       261b           261b
green  open   .fess_config.bad_word              s1zhdMWYQuiqs7uEJybrqg   1   0          0            0       261b           261b
green  open   .crawler.filter                    OoKVEp0vT0uJvFdSyVE4JA   5   0        130           36     43.4kb         43.4kb
green  open   .fess_config.label_type            kEkwn_BIT5CPCP-yT6wljQ   1   0          0            0       261b           261b
green  open   fess_log.search_log                8_80lDVhQhqrRsvWiZReTA   5   0         14            0    129.3kb        129.3kb
green  open   .fess_config.data_config_to_role   TaWSw_1tQYOCA6IHIXkyCw   1   0          0            0       261b           261b
green  open   .fess_config.duplicate_host        GKfK4hxuRaCLWxlqm2SVnQ   1   0          0            0       261b           261b
green  open   .fess_config.file_config_to_label  kA1vEihXRDWLYl2zbbcOuQ   1   0          0            0       261b           261b
green  open   .fess_config.web_authentication    YARwSKNgQE2qgTAPy1VY-A   1   0          0            0       261b           261b
green  open   .suggest_analyzer                  jCTmNKoqS8OO1sGTKR2jEA   1   0          0            0       261b           261b
green  open   .fess_config.crawling_info_param   KLwddtVtT7eqHk4AmY3_MQ   1   0         66            0     30.7kb         30.7kb
green  open   .fess_config.job_log               9uubE2j_SfStW1Roy_0T6A   1   0         11            1     21.7kb         21.7kb
green  open   .fess_config.file_config_to_role   4VCJcrPQSrCwT-E5DD-qOw   1   0          0            0       261b           261b
green  open   .fess_user.group                   2qJY0PsbR3iDKw_SK_fkMQ   1   0          0            0       261b           261b
green  open   .fess_config.access_token          NK3XJmQwQEyK3NPLV2eRsw   1   0          0            0       261b           261b
green  open   .fess_config.label_to_role         fFt5c0nhQBKjh46Xl-XegQ   1   0          0            0       261b           261b
green  open   fess_log.click_log                 EWQY_hLeQeeyEsyKrsMGYg   5   0          0            0      1.2kb          1.2kb
green  open   fess.20180701                      uclmK-llQcafFyuecoaaaA   5   0         31            1      3.7mb          3.7mb
green  open   .fess_config.role_type             EBpijJ5FSJyMlTkGOb4djw   1   0          0            0       261b           261b
green  open   fess_log.favorite_log              YV-t5vwhTSCEho3pYX_NSQ   5   0          0            0      1.2kb          1.2kb
green  open   .fess_config.thumbnail_queue       -EUjiF4aTfOaIP-6L_Jxiw   1   0          0            0       261b           261b
green  open   .fess_config.scheduled_job         0Pvf2qbYSKet7tcAZMy83w   1   0         10            0     10.1kb         10.1kb
green  open   .fess_config.related_content       Xw4FH-dIR32-PMEROiI3jw   1   0          0            0       261b           261b
green  open   fess.suggest.20180701122349        vOoK3NfMTbq0qS1bGdT1LA   1   0          0            0       261b           261b
green  open   .fess_config.data_config_to_label  fdSViHW1S3O6PrJOuqYtag   1   0          0            0       261b           261b
green  open   .fess_config.path_mapping          6iuwbUrURPSFjSg3fMiA2A   1   0          0            0       261b           261b
green  open   .crawler.queue                     4R1kH-vkTM2cOYp3s7Aaew   5   0          0            0      1.2kb          1.2kb
green  open   .suggest_array.fess                2vlIQCl8T4Wi5vt26YblZg   1   0          2            0      8.2kb          8.2kb
green  open   .fess_user.user                    Q1PjrifpRQCvcHGvRlTPYg   1   0          1            0        5kb            5kb
green  open   .fess_config.data_config           czB-3S3tSguf6axb_Gc4IA   1   0          0            0       261b           261b
green  open   .fess_config.web_config_to_label   S4y-9I8HTiC6xNHThYFGvg   1   0          0            0       261b           261b
green  open   .fess_config.web_config            LiqHV3f7Qry55NxgzJ0ZLg   1   0          1            0      7.8kb          7.8kb
green  open   .fess_config.related_query         SC6zNb4SRSqqTksbcF7j8Q   1   0          0            0       261b           261b
green  open   .suggest                           l7shaDEqRDaGGXSxYH-tjA   1   0          1            0      6.7kb          6.7kb
green  open   .configsync                        AQ7u4ufOTpKoa2Bj7G27Aw   1   0         39            0     32.8kb         32.8kb
green  open   .fess_config.crawling_info         UCdXRMROQviGXiYbcFZrVQ   1   0         10            1      8.8kb          8.8kb
green  open   .fess_config.file_authentication   MdsjTaFVQ6uxsijMNgFZbg   1   0          0            0       261b           261b
green  open   .fess_user.role                    jRSi2s3wRA2m2XMKJ9fyMw   1   0          2            0      3.5kb          3.5kb

"fess.20180701"がクロールで取得したデータのように見えるのでインデックスのマッピング情報を確認してみます。クロールしたデータは大きくなるので日付ごとでインデックスを分けているようです。
$ curl -XGET http://localhost:9201/fess.20180701/_mapping\?pretty

{
  "fess.20180701" : {
    "mappings" : {
      "doc" : {
        "dynamic_templates" : [
          {
            "lang_ar" : {
              "match" : "*_ar",
              "mapping" : {
                "analyzer" : "arabic_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_bg" : {
              "match" : "*_bg",
              "mapping" : {
                "analyzer" : "bulgarian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_bn" : {
              "match" : "*_bn",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ca" : {
              "match" : "*_ca",
              "mapping" : {
                "analyzer" : "catalan_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ca" : {
              "match" : "*_ckb-iq",
              "mapping" : {
                "analyzer" : "sorani_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_cs" : {
              "match" : "*_cs",
              "mapping" : {
                "analyzer" : "czech_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_da" : {
              "match" : "*_da",
              "mapping" : {
                "analyzer" : "danish_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_de" : {
              "match" : "*_de",
              "mapping" : {
                "analyzer" : "german_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_el" : {
              "match" : "*_el",
              "mapping" : {
                "analyzer" : "greek_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_en" : {
              "match" : "*_en",
              "mapping" : {
                "analyzer" : "english_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_en" : {
              "match" : "*_en-ie",
              "mapping" : {
                "analyzer" : "irish_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_es" : {
              "match" : "*_es",
              "mapping" : {
                "analyzer" : "spanish_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_et" : {
              "match" : "*_et",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_et" : {
              "match" : "*_eu",
              "mapping" : {
                "analyzer" : "basque_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_fa" : {
              "match" : "*_fa",
              "mapping" : {
                "analyzer" : "persian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_fi" : {
              "match" : "*_fi",
              "mapping" : {
                "analyzer" : "finnish_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_fr" : {
              "match" : "*_fr",
              "mapping" : {
                "analyzer" : "french_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_gl" : {
              "match" : "*_gl",
              "mapping" : {
                "analyzer" : "galician_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_gu" : {
              "match" : "*_gu",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_he" : {
              "match" : "*_he",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_hi" : {
              "match" : "*_hi",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_hr" : {
              "match" : "*_hr",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_hu" : {
              "match" : "*_hu",
              "mapping" : {
                "analyzer" : "hungarian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_hu" : {
              "match" : "*_hy",
              "mapping" : {
                "analyzer" : "armenian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_id" : {
              "match" : "*_id",
              "mapping" : {
                "analyzer" : "indonesian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_it" : {
              "match" : "*_it",
              "mapping" : {
                "analyzer" : "italian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ja" : {
              "match" : "*_ja",
              "mapping" : {
                "analyzer" : "japanese_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ko" : {
              "match" : "*_ko",
              "mapping" : {
                "analyzer" : "korean_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_lt" : {
              "match" : "*_lt",
              "mapping" : {
                "analyzer" : "lithuanian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_lv" : {
              "match" : "*_lv",
              "mapping" : {
                "analyzer" : "latvian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_mk" : {
              "match" : "*_mk",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ml" : {
              "match" : "*_ml",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_nl" : {
              "match" : "*_nl",
              "mapping" : {
                "analyzer" : "dutch_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_no" : {
              "match" : "*_no",
              "mapping" : {
                "analyzer" : "norwegian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_pa" : {
              "match" : "*_pa",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_pl" : {
              "match" : "*_pl",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_pt" : {
              "match" : "*_pt",
              "mapping" : {
                "analyzer" : "portuguese_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_pt-br" : {
              "match" : "*_pt-br",
              "mapping" : {
                "analyzer" : "brazilian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ro" : {
              "match" : "*_ro",
              "mapping" : {
                "analyzer" : "romanian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ru" : {
              "match" : "*_ru",
              "mapping" : {
                "analyzer" : "russian_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_si" : {
              "match" : "*_si",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_sq" : {
              "match" : "*_sq",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_sv" : {
              "match" : "*_sv",
              "mapping" : {
                "analyzer" : "swedish_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ta" : {
              "match" : "*_ta",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_te" : {
              "match" : "*_te",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_th" : {
              "match" : "*_th",
              "mapping" : {
                "analyzer" : "thai_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_tl" : {
              "match" : "*_tl",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_tr" : {
              "match" : "*_tr",
              "mapping" : {
                "analyzer" : "turkish_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_uk" : {
              "match" : "*_uk",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_ur" : {
              "match" : "*_ur",
              "mapping" : {
                "analyzer" : "empty_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_vi" : {
              "match" : "*_vi",
              "mapping" : {
                "analyzer" : "vietnamese_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_zh-cn" : {
              "match" : "*_zh-cn",
              "mapping" : {
                "analyzer" : "simplified_chinese_analyzer",
                "type" : "text"
              }
            }
          },
          {
            "lang_zh-tw" : {
              "match" : "*_zh-tw",
              "mapping" : {
                "analyzer" : "traditional_chinese_analyzer",
                "type" : "text"
              }
            }
          }
        ],
        "properties" : {
          "anchor" : {
            "type" : "keyword"
          },
          "boost" : {
            "type" : "float"
          },
          "cache" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "click_count" : {
            "type" : "long"
          },
          "config_id" : {
            "type" : "keyword"
          },
          "content" : {
            "type" : "langstring",
            "term_vector" : "with_positions_offsets",
            "analyzer" : "standard_analyzer",
            "lang_field" : "lang",
            "lang_base_name" : ""
          },
          "content_ja" : {
            "type" : "text",
            "analyzer" : "japanese_analyzer"
          },
          "content_length" : {
            "type" : "long"
          },
          "content_minhash" : {
            "type" : "minhash",
            "minhash_analyzer" : "minhash_analyzer",
            "copy_bits_to" : [
              "content_minhash_bits"
            ]
          },
          "content_minhash_bits" : {
            "type" : "keyword"
          },
          "created" : {
            "type" : "date",
            "format" : "date_optional_time"
          },
          "digest" : {
            "type" : "text",
            "index" : false
          },
          "doc_id" : {
            "type" : "keyword"
          },
          "expires" : {
            "type" : "date",
            "format" : "date_optional_time"
          },
          "favorite_count" : {
            "type" : "long"
          },
          "filename" : {
            "type" : "keyword"
          },
          "filetype" : {
            "type" : "keyword"
          },
          "has_cache" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "host" : {
            "type" : "keyword"
          },
          "important_content" : {
            "type" : "langstring",
            "index" : false,
            "lang_field" : "lang",
            "lang_base_name" : "title"
          },
          "label" : {
            "type" : "keyword"
          },
          "lang" : {
            "type" : "keyword"
          },
          "last_modified" : {
            "type" : "date",
            "format" : "date_optional_time"
          },
          "location" : {
            "type" : "geo_point"
          },
          "mimetype" : {
            "type" : "keyword"
          },
          "parent_id" : {
            "type" : "keyword"
          },
          "role" : {
            "type" : "keyword"
          },
          "segment" : {
            "type" : "keyword"
          },
          "site" : {
            "type" : "keyword"
          },
          "thumbnail" : {
            "type" : "keyword"
          },
          "timestamp" : {
            "type" : "date",
            "format" : "date_optional_time"
          },
          "title" : {
            "type" : "langstring",
            "term_vector" : "with_positions_offsets",
            "analyzer" : "standard_analyzer",
            "lang_field" : "lang",
            "lang_base_name" : ""
          },
          "title_ja" : {
            "type" : "text",
            "analyzer" : "japanese_analyzer"
          },
          "url" : {
            "type" : "keyword"
          },
          "virtual_host" : {
            "type" : "keyword"
          }
        }
      }
    }
  }
}

多分これが対象のデータのようなので試しに一件出してみます。

$ curl -H "Content-type: application/json" -X GET 'http://localhost:9201/fess.20180701/_search' -d '

{
  "query": { "match_all": {} },
  "_source": ["host", "site", "url", "content"],
   "from": 1,
   "size": 1
}
'
{"took":10,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":31,"max_score":1.0,"hits":[{"_index":"fess.20180701","_type":"doc","_id":"https:%2F%2Fgigazine.net%2Fnews%2F20180701-topvalu-almond-icecream%2F;role=Rguest","_score":1.0,"_source":{"site":"gigazine.net/news/20180701-topvalu-almond-icecr...","host":"gigazine.net","content":"GIGAZINE シークレットクラブ ログイン GIGAZINE シークレットクラブって何? 2018年07月01日 11時45分 試食 アイスなのに生クリームなど乳製品を一切使っていない「トップバリュ アーモンドアイス プレーン」など全3種類を味わってみた 牛乳、豆乳に次ぐ「第3のミルク」と呼ばれているという「アーモンドミルク」で作ったアイスクリーム「 トップバリュ アーモンドアイス 」のフレーバー「プレーン」「チョコレート」「メープルバニラ」が全国のイオングループの各店舗で2018年6月27日(水)から登場しています。乳製品不使用でアーモンドミルクで作ったアイスクリームがどのような味なのか、そもそも植物性の油のみでアイスクリームの食感として成立しているのかが気になったので実際に食べてみました。 株式会社イオントップバリュ株式会社牛乳、豆乳に次ぐ“第3のミルク”がアイスになって登場!乳製品を使用せずアーモンドミルクで作った「トップバリュアーモンドアイス」新発売 (PDFファイル) http://www.aeon.info/news/2018_1/pdf/180625R_2.pdf これが「トップバリュ アーモンドアイス」全3種類。左からフレーバーの「プレーン」「チョコレート」「メープルバニラ」(各税込170円)となっていて、乳製品を使用せずにアーモンドミルクなど作られた「植物性」のアイスクリームです。 「トップバリュ アーモンドアイス」全3種類のカップの大きさは同じで、交通系ICカードを並べるとこんな感じ。イオンでは2018年3月にアーモンドミルクを発売したところ好評で、アーモンドミルクのアイスのリクエストを受けて「アーモンドアイス」全3種類が開発されたとのこと。 ◆トップバリュ アーモンドアイス プレーン 「トップバリュ アーモンドアイス プレーン」(税込170円)は3つのアイスクリームの中でアーモンドミルクの比率が30%と一番割合が大きいアイスクリームです。全3種類のアイスクリームのフタには「※アーモンドの粒は入っておりません。」という注意書きがあります。 ウェブサイト によると全3種類のアイスクリームは乳製品が苦手な人でも食べられるアイスクリームとなっている模様。 アイスクリームの種類は乳固形分で分類されるので、乳製品を使用していないので乳固形分がない「トップバリュ アーモンドアイス」は「氷菓」に分類されているようです。原材料はアーモンド加工品・水あめ・植物油脂・アーモンドペーストなどが含まれていて乳製品が含まれていないのが確認できます。内容量は105ml。 1個あたりのエネルギーは135kcal。 フタを外すと白色の内ブタがかぶせられていました。 内ブタをはがすと「トップバリュ アーモンドアイス プレーン」が登場。 普通のバニラアイスなどの乳白色ではなく、完全な白色なのがわかります。 「乳製品を使っていないアイスクリームはどんな食感なのだろうか?」とおそるおそる食べてみると、口どけが良くてバニラアイスクリームに近い味。口に入れた瞬間に濃厚で香ばしいアーモンドの香りがします。「アーモンドアイス プレーン」の滑らかな舌触りはアイスクリームと細かいシャーベット( ソルベ )の中間ぐらいに感じます。乳製品を使ったアイスクリームより後味がサッパリとしているので、冷たいものを食べたいけれど、口の中を甘ったるくはしたくない時などに良さそうに感じます。 ◆トップバリュ アーモンドアイス チョコレート 「トップバリュ アーモンドアイス チョコレート」(税込170円)はチョコレートのフレーバー。3つのアイスクリームの中で一番アーモンドミルクの割合が低い18%となっています。 原材料は「アーモンドアイス プレーン」に含まれていない「カカオマス」と「ココアパウダー」があるのがわかります。内容量は106mlなので内容量とアイスクリームの種類は「アーモンドアイス プレーン」と同じ。 1個あたりのエネルギーは158kcalで、「アーモンドアイス プレーン」のエネルギーより23kcalほど高い計算になります。 フタを外して、内ブタをはがすと「トップバリュ アーモンドアイス チョコレート」が登場。 食べてみるとチョコレートの香りや苦みを楽しめます。ただし、アーモンドミルクの割合が低いのと、チョコレートの風味の主張が強いからか、アーモンドの香りをはっきりと感じることはできませんでした。チョコレートのフレーバーはアーモンドミルクのお陰か普通のチョコレートアイスクリームよりやや後味がすっきり感じられるところがグッド。 ◆トップバリュ アーモンドアイス メープルバニラ 最後は「トップバリュ アーモンドアイス メープルバニラ」(税込170円)。アーモンドミルクの比率は3つのアイスクリームの中で2番目に高い26%。 原材料は3つのアーモンドアイスの中で唯一「メープルシロップ」と「カラメルソース」が含まれています。内容量は105mlなので内容量とアイスクリームの種類は全3種類とも同じ。 1個あたりのエネルギーは129kcalなので、エネルギーは3つのアーモンドアイスの内で1番低い「アーモンドアイス プレーン」とほぼ同じ。1番高い「アーモンドアイス チョコレート」より29kcal低い計算になります。 「トップバリュ アーモンドアイス メープルバニラ」はほんのりとメープル色で、内ブタをはがすとメープルシロップの甘い香りが漂います。 食べてみるとメープルシロップのやさしい甘さを感じられる口どけの良いアイスクリーム。食べる前は「アーモンドの香りがメープルシロップの香りで掻き消されていないかな?」と思いましたが、アーモンドの芳ばしい香りとメープルシロップの甘い香りを両方感じられる滑らかなアイスクリームに仕上がっていました。 「トップバリュ アーモンドアイス プレーン」「チョコレート」「メープルバニラ」は全国のイオングループ約2000店舗「イオン」「イオンスタイル」「マックスバリュ」「ダイエー」「ピーコックストア」などで購入可能となっています。 ・関連記事 「ミルク」の種類の違いは子どもたちの成長に何か影響を与えているのか? - GIGAZINE インコを口に入れたような風味のインコアイス3種類を食べに行ってきました - GIGAZINE 「飲むアイス」クーリッシュにオレンジ果汁12%と 爽やかなソーダ感をプラスした「まる搾りオレンジソーダ」を味わってみた - GIGAZINE ハーゲンダッツの新シリーズ、マイスイート「春摘み紅茶香る 白桃のタルト」はジューシーな白桃と芳醇な紅茶の三層が絡み合う - GIGAZINE ハーゲンダッツが「さまざまな価値を提案する」という新フレーバーのバーアイス3種類を味わってみた - GIGAZINE 意外性のある味という枝豆フレーバー「がぶ飲み ずんだクリームソーダ」をがぶがぶ飲んでみた - GIGAZINE ・関連コンテンツ ヨーグルト&蜂蜜という組み合わせでもやっぱりリッチなハーゲンダッツ「ハニー&ミルク(ヨーグルト仕立て)」試食レビュー 高級感あふれる本気の「バナナミルク」アイスがハーゲンダッツから発売されたので食べてみた 3種のチョコレートでめくるめく味の変化が楽しめるハーゲンダッツ「トリプルショコラ」を食べてみた ミントなのに白い、セブン限定の「ジャイアントコーン<大人の白いチョコミント>」を食べてみた 抹茶づくしで濃厚な味わいのハーゲンダッツ「抹茶クランブル」を食べてみた ココアクッキーとバナナ果汁の相性が抜群の「明治 エッセルスーパーカップ バナナ&クッキー」を食べてみた あの雪印コーヒーにほろ苦さを加えたプリン「たべる雪印コーヒービターテイスト」を食べてみた Tweet 2018年07月01日 11時45分00秒 in 試食 , Posted by log1f_yi RSS 2.0 「GIGAZINEマンガ大賞」2018年7月度募集開始&トップ画メイキングはこんな感じ マンガ 最新ニュース40件 「クラミジアの国ノルウェーへようこそ!」という広告をノルウェーのセブン-イレブンが出して観光局を怒らせる 「GIGAZINEマンガ大賞」2018年7月度募集開始&トップ画メイキングはこんな感じ アイスなのに生クリームなど乳製品を一切使っていない「トップバリュ アーモンドアイス プレーン」など全3種類を味わってみた 無料で大量のメディア化作品を読めるSQUARE ENIXのマンガアプリ「マンガUP!」 Samsung製のスマホで撮影した写真が無断で送信されるバグが発生 なぜ古代の人々はそら豆を「死の象徴」として恐れていたのか? ピタゴラスイッチの世界をスマートフォンで楽しめる「ピタゴラ うたのアプリ5本セット」を使ってみた メキシコで大統領選中に130人以上の政治家・立候補者が殺される 1000年前のヴァイキングが愛した伝説のボードゲーム「ネファタフル」とは? カラクリのように形状が変化するペーパークラフト「カミカラ」 人間は105歳を超えると「死ににくくなる」という傾向が判明、人類はまだ寿命の上限に達していない可能性も スタバでカクテルのようにシェイクしたイタリア風アイスコーヒー「シェケラート」のフワフワな泡を味わってみた アメリカ人さえもあまり知らない「奇妙なアメリカの地理雑学」とは? 剣闘士は筋骨隆々の戦士ではなく皮下脂肪に覆われ食生活は炭水化物中心だった 鍋にギリギリまで具材を放り込んで誰よりもおいしいカレーを追求するカードゲーム「ギリギリカレー」を遊んでみた ハーゲンダッツの新シリーズ、マイスイート「春摘み紅茶香る 白桃のタルト」はジューシーな白桃と芳醇な紅茶の三層が絡み合う なぜ女性の友情はこんなにも複雑なのか? 魔法の怪しげな雰囲気とワクワク感が詰まった「The House with a Clock in Its Walls」予告編第2弾が公開 「AppleはMacBook Proのキーボードの欠陥で大きな損害を生むことになる」とiFixitのCEOが指摘 細胞擬人化アニメ「はたらく細胞」の高橋祐馬プロデューサーにインタビュー、「献血で第1話試聴」など面白施策を打ち出す裏側とは? 2018年6月29日のヘッドラインニュース ミミまでおいしいという高級食パン嵜本の「極美”ナチュラル”食パン」&「極生”ミルクバター”食パン」を食べてみた 人が「色」を見分けたり「脅威」を感じる基準は驚くほど状況で左右されることが判明 超常現象は「金縛り」や「頭内爆発音症候群」が原因となっている可能性 3億4000万件分の個人情報が公開サーバー上に保存されていたことが判明、被害範囲は「ほぼすべてのアメリカ人」か たった100万円で運送業を開始できるビジネスオーナー支援プログラムをAmazonが開始 エナジードリンクだけを飲み続けると何が起こるのか? アメリカの大手スーパーマーケットが「自動運転カーによる無人配達」を導入すると発表 AmazonがFireタブレットをディスプレイ付きAmazon Echoに変える「Show Mode」を発表 Appleが有機ELパネルの供給をLGディスプレイからも受けることに Twitterが政治広告の透明性を向上する仕様変更を発表、2018年中間選挙を見越してのものか Facebookのクイズアプリから1億2000万人分ものユーザー個人情報が流出していた可能性 ディズニーが映画のヒーローをテーマパークに降臨させるべく進めるロボット開発プロジェクト「Stuntronics」とは? 従来のARをはるかに凌ぐリアルとデジタルの相互作用を実現可能なAR技術「Niantic Occlusion」 3Dプリンターで複雑形状を実現し、電極を内蔵することで照明器具にもなれる「スマートコンクリート壁」 「すべての航空路もローマに通ず」ことを示してくれるインタラクティブマップ「Flights to Rome」 二足歩行ロボットに「不安定な足場を歩く方法」を教えることに研究者が初めて成功 ビル・ゲイツが語る「世界を理解するために覚えておくべき3つのグラフ」とは? WordPressでメディアファイル編集時にサーバー上の任意のファイルを削除可能な脆弱性、バージョン4.9.6でも未修正 GoogleやFacebookではユーザーを意図的に企業が有利な方向へ誘導する「ダークパターン」がどのように使われているのか? 過去の記事 カテゴリ ピックアップ ヘッドライン レビュー 取材 インタビュー 試食 モバイル ソフトウェア ネットサービス ウェブアプリ ハードウェア 乗り物 サイエンス 生き物 動画 映画 マンガ アニメ ゲーム デザイン アート 食 メモ セキュリティ お知らせ コラム メンバー限定 広告 サイト内検索 検索 人気記事ランキング 直近24時間に読まれた記事のランキング 剣闘士は筋骨隆々の戦士ではなく皮下脂肪に覆われ食生活は炭水化物中心だった アメリカ人さえもあまり知らない「奇妙なアメリカの地理雑学」とは? 「AppleはMacBook Proのキーボードの欠陥で大きな損害を生むことになる」とiFixitのCEOが指摘 なぜ女性の友情はこんなにも複雑なのか? エナジードリンクだけを飲み続けると何が起こるのか? ビル・ゲイツが語る「世界を理解するために覚えておくべき3つのグラフ」とは? メキシコで大統領選中に130人以上の政治家・立候補者が殺される 2018年6月29日のヘッドラインニュース 人間は105歳を超えると「死ににくくなる」という傾向が判明、人類はまだ寿命の上限に達していない可能性も 鍋にギリギリまで具材を放り込んで誰よりもおいしいカレーを追求するカードゲーム「ギリギリカレー」を遊んでみた 人気動画 2018-06-23から2018-06-29の再生回数ランキング 1.56秒で180km/hに達する富士急ハイランド「ド・ドドンパ」の加速力3.75Gをプレス向け試乗会で体験してきた シーシェパードのアディ・ギル号が沈没 富士急ハイランド新絶叫マシーン「高飛車」に乗ってみた 「ねこあつめ VR」でねこたちと思う存分戯れてみた 熟練のハンターがイノシシを解体して内臓を取り出しているところ 一筆龍ならぬ「一筆蛇」で「2013」","url":"https://gigazine.net/news/20180701-topvalu-almond-icecream/"}}]}}%

typeとdocはデータは以下のようになりました。

$ curl -H "Content-type: application/json" -X GET 'http://localhost:9201/fess.20180701/_search' -d  '
{
  "query": { "match_all": {} },
  "_source": ["_index", "_type", "_id"],
   "from": 1,
   "size": 1
}
'
{"took":8,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":31,"max_score":1.0,"hits":[{"_index":"fess.20180701","_type":"doc","_id":"https:%2F%2Fgigazine.net%2Fnews%2F20180701-topvalu-almond-icecream%2F;role=Rguest","_score":1.0,"_source":{}}]}}%

javaAPIでデータを取得してみる

javaでElasticserachのクライアントを使えるようにするには、以下のdependencyを追加します。

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>6.3.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>6.3.0</version>
</dependency>

それからデータ取得は以下のようになります。これはインデックスしたクロール情報のうちURLを表示するものになります。

package org.teruuu.elasticsearch.client;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.net.InetAddress;

public class TryElClient {

  public static void main(String[] args){
    TryElClient tryElClient = new TryElClient();
    tryElClient.tryClient();
  }

  public void tryClient(){
    Settings settings = Settings.builder()
            .put("cluster.name", "elasticsearch").build();

    try(TransportClient client = new PreBuiltTransportClient(settings)
            .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9301));){
      System.out.print(client.toString());

      QueryBuilder qb = QueryBuilders.boolQuery().filter(QueryBuilders.wildcardQuery("url", "https://gigazine.net/*"));

      SearchResponse scrollResp = client.prepareSearch("fess.20180701")
              .setTypes("doc")
              .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)
              .setScroll(new TimeValue(60000))
              .setQuery(qb)
              .setSize(100).get();
      do {
        for (SearchHit hit : scrollResp.getHits().getHits()) {
          System.out.println(hit.getSourceAsMap().get("url"));
        }
        scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
      } while(scrollResp.getHits().getHits().length != 0);


      client.close();
    } catch(Exception e){
      e.printStackTrace();
    }
  }
}

pythonAPIでデータを取得してみる

pythonでデータを取得する場合は、ライブラリをインストールしておきます。

pip install elasticsearch

それからスクロールapiを使ってjavaと同様にデータを取得する場合は以下のようになります。

from datetime import datetime
from elasticsearch import Elasticsearch
es = Elasticsearch("http://127.0.0.1:9201")


def scroll(index, doc_type, query_body, page_size=100, scroll='2m'):
    page = es.search(index=index, doc_type=doc_type, scroll=scroll, size=page_size, body=query_body)
    sid = page['_scroll_id']
    scroll_size = page['hits']['total']
    total_pages = math.ceil(scroll_size/page_size)
    page_counter = 0
    # Start scrolling
    while (scroll_size > 0):
        # Get the number of results that we returned in the last scroll
        scroll_size = len(page['hits']['hits'])
        if scroll_size>0:
            yield total_pages, page_counter, scroll_size, page
        # get next page
        page = es.scroll(scroll_id = sid, scroll = '2m')
        page_counter += 1
        # Update the scroll ID
        sid = page['_scroll_id']

index = 'fess.20180701'
doc_type = 'doc'
query = { "query": { "match_all": {} }}
page_size =50
max_size=100

currrent_volume=0
for total_pages, page_counter, page_items, page_data in scroll(index, doc_type, query, page_size=page_size):
    print('total_pages={}, page_counter={}, page_items={}'.format(total_pages, page_counter, page_items))
    for data in page_data['hits']['hits']:
        print(data['_source']['url'])
    currrent_volume += page_items
    if(currrent_volume >= max_size):
        break