連結至 API:分析意見回饋情緒

程式碼程度:中級
所需時間:20 分鐘
專案類型:使用自訂選單進行自動化

目標

  • 瞭解解決方案的功能。
  • 瞭解解決方案中的 Apps Script 服務功能。
  • 設定環境。
  • 設定指令碼。
  • 執行指令碼。

認識這項解決方案

您可以大量分析文字資料,例如開放式意見回饋。如要在 Google 試算表中執行實體和情緒分析,本解決方案會使用 UrlFetch 服務連線至 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。您可以在單一 Google Cloud 專案中啟用一或多個 API。

  • 在 Cloud 專案中,啟用 Google Cloud Natural Language API。

    啟用 API

這項解決方案需要已設定同意畫面 的 Cloud 專案。設定 OAuth 同意畫面可定義 Google 向使用者顯示的內容,並註冊應用程式,以便稍後發布。

  1. 在 Google Cloud 控制台中,依序前往「選單」 > Google Auth platform >「品牌」

    前往「品牌宣傳」

  2. 如果您已設定 Google Auth platform,可以在「品牌」、「目標對象」和「資料存取權」中設定下列 OAuth 同意畫面設定。如果看到「尚未設定」Google Auth platform 訊息,請按一下「開始使用」
    1. 在「App Information」(應用程式資訊) 下方的「App name」(應用程式名稱) 欄位中,輸入應用程式名稱。
    2. 在「使用者支援電子郵件」中,選擇支援電子郵件地址,方便使用者在同意聲明方面有任何疑問時與您聯絡。
    3. 點選 [下一步]
    4. 在「目標對象」下方,選取「內部」
    5. 點選 [下一步]
    6. 在「聯絡資訊」下方,輸入可接收專案異動通知的電子郵件地址
    7. 點選 [下一步]
    8. 在「完成」部分,請詳閱《Google API 服務:使用者資料政策》,然後選取「我同意《Google API 服務:使用者資料政策》」
    9. 按一下 [繼續]。
    10. 按一下「Create」(建立)。
  3. 目前可以略過新增範圍。 日後為 Google Workspace 機構以外的使用者建立應用程式時,請務必將「使用者類型」變更為「外部」。然後新增應用程式需要的授權範圍。詳情請參閱完整的「設定 OAuth 同意畫面」指南。

取得 Google Cloud Natural Language API 的 API 金鑰

  1. 前往 Google Cloud 控制台。請確認您已開啟啟用計費功能的專案。
  2. 在 Google Cloud 控制台中,依序前往「選單」圖示 >「API 和服務」 >「憑證」

    前往「憑證」

  3. 依序按一下「建立憑證」>「API 金鑰」

  4. 記下 API 金鑰,供後續步驟使用。

設定指令碼

建立 Apps Script 專案

  1. 點選下方按鈕,複製「Sentiment analysis for feedback」(意見回饋情緒分析)範例試算表。這個解決方案的 Apps Script 專案會附加至試算表。
    建立副本
  2. 依序點選「擴充功能」>「Apps Script」
  3. 在指令碼檔案中,使用您的 API 金鑰更新下列變數:
    const myApiKey = 'YOUR_API_KEY'; // Replace with your API key.
  4. 按一下「儲存」圖示 「儲存」圖示

新增文字資料

  1. 返回試算表。
  2. idcomments 欄位中加入文字資料。您可以使用 Kaggle 的度假住宿評論範例,也可以使用自己的資料。您可以視需要新增更多資料欄,但如要順利執行指令碼,idcomments 資料欄必須有資料。

執行指令碼

  1. 依序按一下試算表頂端的「情緒分析工具」>「標記實體和情緒」。你可能需要重新整理頁面,才能看到這個自訂選單。
  2. 出現提示訊息時,請授權執行指令碼。 如果 OAuth 同意畫面顯示「這個應用程式未經驗證」警告,請依序選取「進階」>「前往『{專案名稱}』(不安全)」,繼續操作。

  3. 依序點選「情緒工具」> 再次點選「標記實體和情緒」

  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 維護,並由 Google 開發人員專家協助。

後續步驟