感情分析でハッピーな記事しか掲載しないニュースサイトを作る！

## はじめに

テキスト分析系のAPIによくある「感情分析」
この活用方法がいまいちピンと来てなかったのですが、先日の勉強会で news と合わせて使う事例を聞いたので、試しに少し作ってみました。

## やりたいこと

【Happyなニュースだけを届けるニュースサイト】
※今回はバックエンドのみ

全世界のコロナ騒動の問題もあってか、最近は印象が悪いニュースが多い気がする。。
なので「嫌なことには目を背けよう」的な思考でマイナスな感情を淘汰したハッピーなニュースサイトを作って気分良くなりたい！

## API

- [News API](https://newsapi.org/)
- [Google Natural Language API](https://cloud.google.com/natural-language/docs?hl=ja)  (感情分析)

今回はどちらも、提供されているクライアントライブラリを使用して、Node.jsで実装しました

### [News API](https://newsapi.org/)

使用するのは、事前にアカウントを作成しAPIキーを取得する必要があります。

- Top headlines：最新のヘッドライン
- Everything：全ての記事
- Source ：Top headlines が利用できるニュースパブリッシャーのサブセットを返す

以上の三つがエンドポイントとして提供されており、クライアントライブラリではそれぞれメソッドとして使用することができます。今回は最新のニュースの結果を返してくれる「Top headlines」を使用しています。リクエストパラメータには、カテゴリーや検索フレーズを指定することが出来るので求めたいニュースに合わせて値を設定すると良いです。

### [Natural Language API](https://cloud.google.com/natural-language/docs?hl=ja)

使用に際しては[公式](https://cloud.google.com/natural-language/docs/quickstart-client-libraries?hl=ja)を参照してみてください。

Natural Language API で分析できる感情は、`score` と `magnitude` の数値によって表されます。
二つの値の解釈は以下のようになっており、ポジティブとネガティブを -1.0 ~ 1.0 で score が表すのに対し、magnitude は感情の大きさを 0 以上で表します。つまり、ポジティブとネガティブの割合が同等で相殺され、score が 0 になるパターンを、magnitude の値で判別することができるようになります。 

> 感情分析の値の解釈
ドキュメントの感情分析の score は、ドキュメントの全体的な感情を示します。ドキュメントの感情分析の magnitude は、そのドキュメントに感情的な内容がどのくらい含まれているかを示します。この値は、ドキュメントの長さに比例する傾向があります。

## コード

二つのファイルに分割

``` jsx:news.js
const NewsAPI = require('newsapi');
const func = require('./sentiment');
const newsapi = new NewsAPI('{ YOUR_KEY }');
newsapi.v2.topHeadlines({
    category: 'business', 
    country: 'jp',
}).then( news => {
    news['articles'].forEach(item => {
        func.sentiment(item.title) // ニュースのタイトルを分析にかける
    });
});
```

```jsx:sentiment.js
exports.sentiment =  async function (text) {
    const language = require('@google-cloud/language');
    const client = new language.LanguageServiceClient();
    const document = {
        language: 'ja',
        content: text,
        type: 'PLAIN_TEXT',
    };

    const [result] = await client.analyzeSentiment({ document });

    const sentences = result.sentences;
    sentences.forEach(sentence => {
        if(sentence.sentiment.score > 0){ // ハッピーなタイトルのみ表示
            console.log(`Sentence: ${sentence.text.content}`);
            console.log(`  Score: ${sentence.sentiment.score}`);
            console.log(`  Magnitude: ${sentence.sentiment.magnitude}`);
        }
    });
};
```

`node news` で結果を表示する、、

```bash
Sentence: この冬はこたつで無限にゲームしたい。
  Score: 0.20000000298023224
  Magnitude: 0.20000000298023224
Sentence: 振込手数料を値下げへ 銀行間送金、少額ほど安く - 日本経済新聞
  Score: 0.20000000298023224
  Magnitude: 0.20000000298023224
Sentence: 【明日の好悪材料】を開示情報でチェック！
  Score: 0.10000000149011612
  Magnitude: 0.10000000149011612
Sentence: BMW、早くも新型「M5/M5 コンペティション」「M550i xDrive」日本導入 - Car Watch
  Score: 0.10000000149011612
  Magnitude: 0.10000000149011612
Sentence: 飲食店効率化「配膳ロボ」の実力 非接触ニーズにも対応 - FNNプライムオンライン
  Score: 0.6000000238418579
  Magnitude: 0.6000000238418579
```

※2020年9月末時点の結果

こたつで無限にゲーム、、笑
どこのワードがポジティブ要因に引っかかっているかは分かりませんが、これは間違いなくプラスの感情ですね笑

最後のSentenceは、「効率化」や「ニーズにも対応」など好印象のワードが揃っているので、score が高くなっているのが分かりますね！

## まとめ

制作に関してはどちらのAPIのドキュメントもとても充実して読みやすかったので、実装自体で特に苦しむポイントはなかったです。次回はフロント部分の方にを手を加えてもう少しNewsサイトっぽいものに近づけたいと思います！

個人的に感情分析ってシンプルなようで活用方法が難しい気がするので(僕の発想力に問題あり)、なにかアイデアある方いれば是非教えて頂きたいです🙇‍♂️