API에 연결하기: 의견 감정 분석

코딩 수준: 중급
소요 시간: 20분
프로젝트 유형: 맞춤 메뉴를 사용한 자동화

목표

  • 솔루션의 작동 방식을 이해합니다.
  • 솔루션 내에서 Apps Script 서비스가 하는 작업을 이해합니다.
  • 환경을 설정합니다.
  • 스크립트를 설정합니다.
  • 스크립트를 실행합니다.

이 솔루션 정보

서술형 의견과 같은 텍스트 데이터를 대규모로 분석할 수 있습니다. 이 솔루션은 Google Sheets 내에서 항목 및 감정 분석을 실행하기 위해 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 프로젝트에서 사용 설정해야 합니다. 단일 Google Cloud 프로젝트에서 하나 이상의 API를 사용 설정할 수 있습니다.

  • Cloud 프로젝트에서 Google Cloud Natural Language API를 사용 설정합니다.

    API 사용 설정

이 솔루션을 사용하려면 동의 화면이 구성된 Cloud 프로젝트가 필요합니다. OAuth 동의 화면을 구성하면 Google에서 사용자에게 표시할 내용이 정의되고 나중에 앱을 게시할 수 있도록 앱이 등록됩니다.

  1. Google Cloud 콘솔에서 메뉴 > API 및 서비스 > OAuth 동의 화면으로 이동합니다.

    OAuth 동의 화면으로 이동

  2. 사용자 유형에서 내부를 선택한 다음 만들기를 클릭합니다.
  3. 앱 등록 양식을 작성한 후 저장 및 계속을 클릭합니다.
  4. 지금은 범위 추가를 건너뛰고 저장하고 계속을 클릭해도 됩니다. 향후 Google Workspace 조직 외부에서 사용할 앱을 만들 때는 사용자 유형외부로 변경한 후 앱에 필요한 승인 범위를 추가해야 합니다.

  5. 앱 등록 요약을 검토합니다. 변경하려면 수정을 클릭합니다. 앱 등록이 올바른 것으로 보이면 대시보드로 돌아가기를 클릭합니다.

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. idcomments 열에 텍스트 데이터를 추가합니다. Kaggle의 샘플 공유숙박 시설 리뷰를 사용하거나 자체 데이터를 사용할 수 있습니다. 필요한 경우 열을 더 추가할 수 있지만 스크립트를 실행하려면 idcomments 열에 데이터가 있어야 합니다.

스크립트 실행

  1. 스프레드시트 상단에서 Sentiment Tools(감정 도구) > Mark entities and sentiment(항목 및 감정 표시)를 클릭합니다. 이 맞춤 메뉴가 표시되려면 페이지를 새로고침해야 할 수도 있습니다.
  2. 메시지가 표시되면 스크립트를 승인합니다. OAuth 동의 화면에 이 앱은 확인되지 않았습니다라는 경고가 표시되면 고급 > {프로젝트 이름}으로 이동(안전하지 않음)을 선택하여 계속 진행합니다.

  3. Sentiment Tools(감정 도구) > Mark entities 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에서 Google 개발자 전문가의 도움을 받아 유지관리합니다.

다음 단계