קישור ל-API: ניתוח סנטימנט של משוב

רמת תכנות: בינונית
משך: 20 דקות
סוג פרויקט: אוטומציה עם תפריט בהתאמה אישית

מטרות

  • הבנה מה הפתרון עושה.
  • להבין מה שירותי Apps Script עושים במסגרת הפתרון.
  • הגדרת הסביבה.
  • מגדירים את הסקריפט.
  • מריצים את הסקריפט.

מידע על הפתרון הזה

ניתן לנתח נתוני טקסט, כמו משוב שאלות ותשובות, בקנה מידה נרחב. כדי לבצע ניתוח ישויות וסנטימנטים מתוך Google Sheets, הפתרון הזה משתמש ב-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 Cloud שמשויך לחשבון לחיוב. אפשר לקרוא במאמר הפעלת החיוב בפרויקט.

הגדרת הסביבה

פתיחת הפרויקט ב-Cloud במסוף Google Cloud

אם הוא לא פתוח, פותחים את הפרויקט ב-Cloud שבו אתם מתכוונים להשתמש בדוגמה הזו:

  1. נכנסים לדף Select a project במסוף Google Cloud.

    בחירת פרויקט ב-Cloud

  2. בוחרים את הפרויקט ב-Google Cloud שבו רוצים להשתמש. לחלופין, לוחצים על יצירת פרויקט ופועלים לפי ההוראות שבמסך. אם אתם יוצרים פרויקט ב-Google Cloud, ייתכן שאתם צריכים להפעיל את החיוב בפרויקט.

הפעלת Google Cloud Natural Language API

הפתרון הזה מתחבר ל-Google Cloud Natural Language API. כדי להשתמש ב-Google APIs, צריך להפעיל אותם בפרויקט ב-Google Cloud. אפשר להפעיל ממשק API אחד או יותר בפרויקט אחד ב-Google Cloud.

  • בפרויקט Cloud, מפעילים את Google Cloud Natural Language API.

    הפעלת ה-API

כדי להשתמש בפתרון הזה נדרש פרויקט ב-Cloud עם מסך הסכמה מוגדר. מסך ההסכמה של OAuth מגדיר את מה ש-Google מציגה למשתמשים, רושם את האפליקציה כך שתוכלו לפרסם אותה מאוחר יותר.

  1. במסוף Google Cloud, נכנסים לתפריט > APIs & Services > מסך ההסכמה של OAuth.

    מעבר למסך ההסכמה של OAuth

  2. בהגדרה סוג משתמש, בוחרים באפשרות פנימי ולוחצים על יצירה.
  3. ממלאים את טופס ההרשמה לאפליקציה ולוחצים על שמירה והמשך.
  4. בינתיים, אפשר לדלג על הוספת היקפים וללחוץ על שמירה והמשך. בעתיד, כשיוצרים אפליקציה לשימוש מחוץ לארגון ב-Google Workspace, צריך לשנות את סוג המשתמש לחיצוני ואז להוסיף את היקפי ההרשאות שנדרשים לאפליקציה.

  5. לבדוק את הסיכום של רישום האפליקציה. כדי לבצע שינויים, לוחצים על עריכה. אם הרישום של האפליקציה נראה בסדר, לוחצים על Back to Dashboard (חזרה למרכז השליטה).

קבלת מפתח API ל-Google Cloud Natural Language API

  1. נכנסים למסוף Google Cloud. מוודאים שהפרויקט המופעל על ידי חיוב פתוח.
  2. במסוף Google Cloud, נכנסים לתפריט > APIs & Services > Credentials.

    כניסה לדף Credentials

  3. לוחצים על Create credentials > API key.

  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 ו-הערות. אתם יכולים להשתמש בדוגמאות של ביקורות על נכסי חופשה מ-Kaggle או להשתמש בנתונים משלכם. אפשר להוסיף עוד עמודות במקרה הצורך, אבל כדי שהסקריפט ירוץ בהצלחה, הוא צריך לכלול נתונים בעמודות id ו-תגובות.

מריצים את הסקריפט

  1. בחלק העליון של הגיליון האלקטרוני, לוחצים על כלים עבור סנטימנטים > סימון ישויות וסנטימנט. ייתכן שתצטרכו לרענן את הדף כדי שהתפריט המותאם אישית יופיע.
  2. כשתוצג בקשה, מאשרים את הסקריפט. אם במסך ההסכמה של OAuth מוצגת האזהרה האפליקציה הזו לא מאומתת, אפשר להמשיך בלחיצה על אפשרויות מתקדמות > מעבר אל {Project Name} (לא בטוח).

  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.

השלבים הבאים