API への接続: フィードバックの感情を分析する

コーディング レベル: 中級
所要時間: 20 分
プロジェクトの種類: カスタム メニューを使用した自動化

目標

  • ソリューションの機能を理解します。
  • Apps Script サービスがソリューション内でどのように機能するかを理解します。
  • 環境を設定する。
  • スクリプトを設定します。
  • スクリプトを実行します。

このソリューションについて

自由回答形式のフィードバックなどのテキストデータを大規模に分析できます。このソリューションでは、Google スプレッドシート内からエンティティと感情の分析を行うために、UrlFetch Service を使用して Google Cloud Natural Language API に接続します。

感情分析の仕組みを示す図

仕組み

このスクリプトは、スプレッドシートからテキストを収集し、Google Cloud Natural Language API に接続して、文字列に含まれるエンティティと感情を分析します。ピボット テーブルは、テキストデータのすべての行について言及された各エンティティの平均感情スコアを要約します。

Apps Script サービス

このソリューションでは、次のサービスを使用します。

  • スプレッドシート サービス - テキストデータを Google Cloud Natural Language API に送信し、感情が分析されたら各行に「完了」のマークを付けます。
  • UrlFetch サービス - Google Cloud Natural Language API に接続して、テキストのエンティティ分析と感情分析を行います。

前提条件

このサンプルを使用するには、次の前提条件を満たす必要があります。

  • Google アカウント(Google Workspace アカウントの場合、管理者の承認が必要になる場合があります)。
  • インターネットにアクセスできるウェブブラウザ。

  • 請求先アカウントが関連付けられた Google Cloud プロジェクト。プロジェクトの課金を有効にするをご覧ください。

環境を設定する

Google Cloud コンソールで Cloud プロジェクトを開く

まだ開いていない場合は、このサンプルで使用する Cloud プロジェクトを開きます。

  1. Google Cloud コンソールで [プロジェクトの選択] ページに移動します。

    Cloud プロジェクトを選択

  2. 使用する Google Cloud プロジェクトを選択します。または、[プロジェクトを作成] をクリックし、画面の指示に従います。Google Cloud プロジェクトを作成する場合は、プロジェクトの課金を有効にすることが必要な場合があります。

Google Cloud Natural Language API を有効にする

このソリューションは、Google Cloud Natural Language API に接続します。Google API を使用する前に、Google Cloud プロジェクトで API を有効にする必要があります。1 つの Google Cloud プロジェクトで 1 つ以上の API を有効にできます。

このソリューションでは、同意画面が構成された Cloud プロジェクトが必要です。OAuth 同意画面を構成すると、Google がユーザーに表示する内容を定義し、後で公開できるようにアプリを登録します。

  1. Google Cloud コンソールで、メニュー > [API とサービス] > [OAuth 同意画面] に移動します。

    OAuth 同意画面に移動

  2. [ユーザーの種類] で [内部] を選択し、[作成] をクリックします。
  3. アプリ登録フォームに入力し、[保存して次へ] をクリックします。
  4. 現時点では、スコープの追加をスキップして、[Save and Continue] をクリックします。今後、Google Workspace 組織外で使用するアプリを作成する場合は、[ユーザータイプ] を [外部] に変更してから、アプリに必要な認証スコープを追加する必要があります。

  5. アプリ登録の概要を確認します。変更するには、[編集] をクリックします。アプリ登録に問題がない場合は、[Back to Dashboard] をクリックします。

Google Cloud Natural Language API の API キーを取得する

  1. Google Cloud コンソールに移動します。 課金が有効になっているプロジェクトが開いていることを確認します。
  2. Google Cloud コンソールで、メニュー > [API とサービス] > [認証情報] に移動します。

    [認証情報] に移動

  3. [認証情報を作成] > [API キー] をクリックします。

  4. 後のステップで使用するために、API キーをメモしておきます。

スクリプトを設定する

Apps Script プロジェクトを作成する

  1. 下のボタンをクリックすると、フィードバックの感情分析のサンプル スプレッドシートのコピーが作成されます。このソリューションの Apps Script プロジェクトは、スプレッドシートに添付されています。
    コピーを作成
  2. [拡張機能] > [Apps Script] をクリックします。
  3. スクリプト ファイルの次の変数を API キーで更新します。
    const myApiKey = 'YOUR_API_KEY'; // Replace with your API key.
  4. 保存アイコン[保存] をクリックします。

テキストデータを追加する

  1. スプレッドシートに戻ります。
  2. id 列と comments 列にテキストデータを追加します。Kaggle からサンプルの民泊施設のレビューを使用することも、独自のデータを使用することもできます。必要に応じて列を追加できますが、スクリプトを正常に実行するには、スクリプトの id 列と comments 列にデータが含まれている必要があります。

スクリプトを実行する

  1. スプレッドシートの上部にある [Sentiment Tools] > [Mark entity and sentiment] をクリックします。このカスタム メニューを表示するには、ページの更新が必要になる場合があります。
  2. プロンプトが表示されたら、スクリプトを承認します。OAuth 同意画面に「このアプリは確認されていません」という警告が表示された場合は、[詳細設定] > [{プロジェクト名}(安全でない)に移動] を選択します。

  3. [Sentiment Tools] > [Mark entity and sentiment] を再度クリックします。

  4. スクリプトが終了したら、[ピボット テーブル] シートに切り替えて結果を確認します。

コードを確認する

このソリューションの Apps Script コードを確認するには、下の [ソースコードを表示] をクリックします。

ソースコードを表示

Code.gs

solutions/automations/feedback-sentiment-analysis/code.js
// To learn how to use this script, refer to the documentation:
// https://developers.google.com/apps-script/samples/automations/feedback-sentiment-analysis

/*
Copyright 2022 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Sets API key for accessing Cloud Natural Language API.
const myApiKey = 'YOUR_API_KEY'; // Replace with your API key.

// Matches column names in Review Data sheet to variables.
let COLUMN_NAME = {
  COMMENTS: 'comments',
  ENTITY: 'entity_sentiment',
  ID: 'id'
};

/**
 * Creates a Demo menu in Google Spreadsheets.
 */
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Sentiment Tools')
    .addItem('Mark entities and sentiment', 'markEntitySentiment')
    .addToUi();
};

/**
* Analyzes entities and sentiment for each comment in  
* Review Data sheet and copies results into the 
* Entity Sentiment Data sheet.
*/
function markEntitySentiment() {
  // Sets variables for "Review Data" sheet
  let ss = SpreadsheetApp.getActiveSpreadsheet();
  let dataSheet = ss.getSheetByName('Review Data');
  let rows = dataSheet.getDataRange();
  let numRows = rows.getNumRows();
  let values = rows.getValues();
  let headerRow = values[0];

  // Checks to see if "Entity Sentiment Data" sheet is present, and
  // if not, creates a new sheet and sets the header row.
  let entitySheet = ss.getSheetByName('Entity Sentiment Data');
  if (entitySheet == null) {
   ss.insertSheet('Entity Sentiment Data');
   let entitySheet = ss.getSheetByName('Entity Sentiment Data');
   let esHeaderRange = entitySheet.getRange(1,1,1,6);
   let esHeader = [['Review ID','Entity','Salience','Sentiment Score',
                    'Sentiment Magnitude','Number of mentions']];
   esHeaderRange.setValues(esHeader);
  };

  // Finds the column index for comments, language_detected, 
  // and comments_english columns.
  let textColumnIdx = headerRow.indexOf(COLUMN_NAME.COMMENTS);
  let entityColumnIdx = headerRow.indexOf(COLUMN_NAME.ENTITY);
  let idColumnIdx = headerRow.indexOf(COLUMN_NAME.ID);
  if (entityColumnIdx == -1) {
    Browser.msgBox("Error: Could not find the column named " + COLUMN_NAME.ENTITY + 
                   ". Please create an empty column with header \"entity_sentiment\" on the Review Data tab.");
    return; // bail
  };

  ss.toast("Analyzing entities and sentiment...");
  for (let i = 0; i < numRows; ++i) {
    let value = values[i];
    let commentEnCellVal = value[textColumnIdx];
    let entityCellVal = value[entityColumnIdx];
    let reviewId = value[idColumnIdx];

    // Calls retrieveEntitySentiment function for each row that has a comment 
    // and also an empty entity_sentiment cell value.
    if(commentEnCellVal && !entityCellVal) {
        let nlData = retrieveEntitySentiment(commentEnCellVal);
        // Pastes each entity and sentiment score into Entity Sentiment Data sheet.
        let newValues = []
        for (let entity in nlData.entities) {
          entity = nlData.entities [entity];
          let row = [reviewId, entity.name, entity.salience, entity.sentiment.score, 
                     entity.sentiment.magnitude, entity.mentions.length
                    ];
          newValues.push(row);
        }
      if(newValues.length) {
        entitySheet.getRange(entitySheet.getLastRow() + 1, 1, newValues.length, newValues[0].length).setValues(newValues);
      }
        // Pastes "complete" into entity_sentiment column to denote completion of NL API call.
        dataSheet.getRange(i+1, entityColumnIdx+1).setValue("complete");
     }
   }
};

/**
 * Calls the Cloud Natural Language API with a string of text to analyze
 * entities and sentiment present in the string.
 * @param {String} the string for entity sentiment analysis
 * @return {Object} the entities and related sentiment present in the string
 */
function retrieveEntitySentiment (line) {
  let apiKey = myApiKey;
  let apiEndpoint = 'https://language.googleapis.com/v1/documents:analyzeEntitySentiment?key=' + apiKey;
  // Creates a JSON request, with text string, language, type and encoding
  let nlData = {
    document: {
      language: 'en-us',
      type: 'PLAIN_TEXT',
      content: line
    },
    encodingType: 'UTF8'
  };
  // Packages all of the options and the data together for the API call.
  let nlOptions = {
    method : 'post',
    contentType: 'application/json',  
    payload : JSON.stringify(nlData)
  };
  // Makes the API call.
  let response = UrlFetchApp.fetch(apiEndpoint, nlOptions);
  return JSON.parse(response);
};

協力者

このサンプルは、Google Developer Experts の協力により Google が保守しています。

次のステップ