Yahoo 日本語形態素解析 API ver2 を叩く

# 前提
- Ruby 2.7.4
    - Faraday 1.7.0
- [Yahoo API ver2](https://developer.yahoo.co.jp/webapi/jlp/ma/v2/parse.html)
    - [ver1](https://developer.yahoo.co.jp/webapi/jlp/ma/v1/parse.html) との違い
        - リクエストが、GET から POST
            - 1リクエストの最大サイズが、100KB から 4KB
        - レスポンスが、XML から JSON
            - また、以前は、解析内容について、設定が行えた
                - 例えば、出現頻度情報を返すようにしたり、名詞に関する情報のみ返すようにしたり


# サンプル
- [リクエスト制限](https://developer.yahoo.co.jp/webapi/jlp/faq.html#requestlimit)を考慮してリトライ設定を行う
    - 1つのアプリケーションIDに対して、1分で300回を超えた場合に、429 Too Many Requestsのエラーレスポンスが返る

```ruby
# 必要な require している前提

module YahooApi
  class MaServiceClient
    REQUEST_URL = 'https://jlp.yahooapis.jp/'
    REQUEST_PATH = 'MAService/V2/parse'
    APP_ID = ENV['YAHOO_MA_SERVICE_APP_ID'] # 事前に設定しましょう

    RETRY_MAX_COUNT = 5
    RETRY_INTERVAL_SECONDS = 90 # 1分間のリクエスト上限に達した場合のリトライを想定
    BACKOFF_FACTOR_SECONDS = 10
    RETRIABLE_EXCEPTIONS = [
      Faraday::ClientError,
      Faraday::TimeoutError,
      Faraday::ConnectionFailed,
      Faraday::ServerError
    ].freeze
    TOO_MANY_REQUESTS_STATUS_CODE = 429

    def initialize(sentence:)
      @sentence = sentence
      @connection = Faraday.new(url: REQUEST_URL) {|builder|
        builder.request :json
        builder.request :retry,
                        max: RETRY_MAX_COUNT,
                        interval: RETRY_INTERVAL_SECONDS,
                        backoff_factor: BACKOFF_FACTOR_SECONDS,
                        exceptions: RETRIABLE_EXCEPTIONS,
                        methods: [],
                        retry_if: ->(env, _exception) { env.status == TOO_MANY_REQUESTS_STATUS_CODE || (400..499).exclude?(env.status) }

        builder.response :json
        builder.response :raise_error

        builder.adapter Faraday.default_adapter
      }
    end

    def request
      response = connection.post(REQUEST_PATH, params, headers)

      response.body
    end

    private

    attr_reader :sentence, :connection

    def params
      {
        id: SecureRandom.uuid,
        jsonrpc: '2.0',
        method: 'jlp.maservice.parse',
        params: {
          q: sentence
        }
      }
    end

    def headers
      {
        'User-Agent': "Yahoo AppID: #{APP_ID}"
      }
    end
  end
end

# main

s = '植物（しょくぶつ、英: plant）とは、生物区分のひとつ。'

YahooApi::MaServiceClient.new(sentence: s).request
# =>
# {"id"=>"2b1e4d03-2f2e-4ee5-b600-c77e210a80f1", "jsonrpc"=>"2.0", "result"=>{"tokens"=>[["植物", "しょくぶつ", "植物", "名詞", "普通名詞", "*", "*"], ["（", "（", "（", "特殊", "括弧始", "*", "*"], ["しょくぶつ", "しょくぶつ", "しょくぶつ", "名詞", "普通名詞", "*", "*"], ["、", "、", "、", "特殊", "読点", "*", "*"], ["英", "えい", "英", "名詞", "人名", "*", "*"], [":", ":", ":", "未定義語", "その他", "*", "*"], [" ", " ", " ", "未定義語", "その他", "*", "*"], ["plant", "plant", "plant", "未定義語", "アルファベット", "*", "*"], ["）", "）", "）", "特殊", "括弧終", "*", "*"], ["と", "と", "と", "助詞", "格助詞", "*", "*"], ["は", "は", "は", "助詞", "副助詞", "*", "*"], ["、", "、", "、", "特殊", "読点", "*", "*"], ["生物", "せいぶつ", "生物", "名詞", "普通名詞", "*", "*"], ["区分", "くぶん", "区分", "名詞", "サ変名詞", "*", "*"], ["の", "の", "の", "助詞", "接続助詞", "*", "*"], ["ひと", "ひと", "ひと", "名詞", "数詞", "*", "*"], ["つ", "つ", "つ", "接尾辞", "名詞性名詞助数辞", "*", "*"], ["。", "。", "。", "特殊", "句点", "*", "*"]]}}
```

# 参考
- [Faraday Usage](https://lostisland.github.io/faraday/usage/)
- [Faradayの使い方 59のレシピ](https://nekorails.hatenablog.com/entry/2018/09/28/152745)
- [Ruby Doc](https://www.rubydoc.info/gems/faraday/0.15.3/Faraday/Request/Retry)