如何用Python和Twilio SMS构建城市词典表情符号/俚语情感分析器

193 阅读8分钟

表情符号和俚语不仅有不同的细微差别,而且在不同人群中的解释也有很大的不同。例如,你的同事会不会误用🙂这个表情符号?为什么🙃比🙂有更多的积极情绪呢?

在本教程中,你将用Python和Twilio SMS建立一个情感分析器,使用Urban Dictionary作为最新俚语的参考。

前提条件

要继续学习本教程,你将需要。

获得一个Twilio电话号码

如果你还没有从Twilio获得一个电话号码,你可以为你的账户购买一个。即使你是试用账户,你的余额上也会有试用的信用额度,可以进行实验。

首先,登录你的账户,console.twilio.com/。在你仪表板的左侧,导航到电话号码>管理>购买号码

Twilio dashboard with multi-level navigation on the left-hand side. The user clicks on the "Phone Numbers" > Manage > "Buy a number" link.

购买号码页面上找到你喜欢的合适的电话号码,然后购买它。

设置你的项目环境

在你深入学习代码之前,你需要设置你的环境。首先,你应该创建一个存放项目的父目录。在你的计算机上打开终端,导航到一个适合你的项目的目录,输入以下命令,然后点击回车。

mkdir urbandict-sms-project && cd urbandict-sms-project

作为Python良好实践的一部分,你还应该创建一个虚拟环境。如果你在 UNIX 或 macOS 上工作,运行下面的命令来创建和激活一个虚拟环境。

python3 -m venv venv
source venv/bin/activate

然而,如果你是在 Windows 上工作,请运行这些命令代替。

python -m venv venv
venv\bin\activate

在激活了虚拟环境之后,你将安装一些 Python 包。在本教程中,你将使用以下软件包。

要安装这些包,运行这个命令。

pip install flask python-dotenv twilio urllib3 nltk

之后,你需要从自然语言工具包中安装一些必要的数据。在命令行中键入并输入python3 。这将启动一个python shell。然后,键入并输入以下几行。

import nltk
nltk.download('vader_lexicon')
nltk.download('stopwords')
exit()

接下来,你的应用程序将需要验证你的Twilio账户凭证。要做到这一点,你的账户凭证将作为环境变量储存在*.en文件中。在urbandict-sms-project目录下,打开一个名为.env*的新文件,将以下内容粘贴到该文件中。

TWILIO_ACCOUNT_SID=XXXXXXXXXXXXXXXX
TWILIO_AUTH_TOKEN=XXXXXXXXXXXXXXXX

注意:你必须用你的Twilio账户的相应数值替换 "XXXXXXXXXXXXX"。你可以在Twilio控制台的 "账户信息"下访问这些值。

Account Info box with two read-only fields "Account SID" and "Auth Token"

你的环境已经设置好了。现在你可以开始创建应用程序了。

创建情感分析器

计划

在编码之前,了解代码应该完成的任务是一个很好的做法。下面是这个程序的预期动作序列。

  • 用户给一个电话号码发一个搜索查询短信。该查询可以是一个表情符号,一个单词,或多个单词。
  • 该程序应搜索Urban Dictionary的API,以获得搜索结果的定义。
  • 该应用程序分析定义的文本。它发现情绪的极性,以及前10个最频繁的词。
  • 该应用程序将这些信息发回给用户。

编码

现在你可以开始编写程序了。在urbandict-sms-project目录下打开一个名为app.py的新文件,并在该文件中粘贴以下代码。

from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
from nltk.sentiment import SentimentIntensityAnalyzer
from nltk.corpus import stopwords
import json
from urllib.request import urlopen
from urllib.parse import quote

app = Flask(__name__)
sia = SentimentIntensityAnalyzer()

stop_list = stopwords.words("english")
stop_list += ["emoji", "you're", "it's", "used", ""]

def reply(text):
    resp = MessagingResponse()
    resp.message(text)
    return str(resp)

@app.route("/analyze", methods=['GET','POST'])
def analyze():
    body = request.form['Body'] # obtain text from user
    query = quote(body) # format special characters for URL query

    # search for the query in Urban Dictionary's API
    with urlopen(f'https://api.urbandictionary.com/v0/define?term={query}') as f:
        data = json.loads(f.read())

    # Concatenate each urban dictionary definition into one string and formatting
    # the text by removing special characters and lowercasing it
    definitions = ""
    for d in data['list']:
        definitions += ' ' + d['definition']
    definitions = definitions.translate({ord(x): ' ' for x in "[].?(),\"/;"})
    definitions = definitions.lower()

    # Counting and sorting words in the text (excluding stop words) with the
    # highest frequency
    keywords = {}
    for word in definitions.split(" "):
        if word not in stop_list:
            if word not in keywords:
                keywords[word] = 1
            else:
                keywords[word] += 1
    sorted_keywords = sorted(keywords, key=keywords.get, reverse=True)

    # Get and print polarity scores, print top 10 keywords
    scores = sia.polarity_scores(definitions)
    ret = f'Polarity Scores:\
        \nPositive {scores["pos"]}\
        \nNeutral {scores["neu"]}\
        \nNegative {scores["neg"]}\
        \nCompound {scores["compound"]}\n\n'
    ret += "Keywords:\n" + ", ".join(sorted_keywords[:10])

    return reply(ret)

在代码中,有几件事需要注意。在导入模块和应用程序后,Flask和SentimentIntensityAnalyzer被初始化。SentimentIntensityAnalyzer使用VADER,这是一个来自自然语言工具箱的预训练模型,可以进行情感分析。在这种情况下,该模型分析城市词典中文本的情感。

这个应用程序不仅分析了所查询内容的极性,而且,它还会跟踪被提及的频繁词汇。由于那些意义不大的词往往出现的频率最高(例如,"the "这个词),这些词应该从计数中排除。nltk软件包中包含了一个预制的这些词的列表,被称为停止词。这段代码在列表中增加了一些停止词,并将它们排除在计数之外。

辅助函数reply(text) 被用来创建一个TwiMLMessagingResponse 对象,这样应用程序就可以向用户发送一个信息。

analyze() 函数中,从用户那里获得文本信息。然后文本被格式化并在Urban Dictionary的API中搜索,返回定义。然后,这些定义被串联起来,并分析其极性和词频。然后,这些信息被返回并发送给用户。

设置ngrok隧道和webhook

如果你过早地运行该程序,你将不会收到来自电话号码的信息。有两件事需要解决。首先,你需要通过打开ngrok隧道到你的本地机器,将你的本地服务器连接到一个可公开访问的URL。第二,你需要通过使用webhook将Twilio电话号码连接到应用程序。

在你的机器上安装了ngrok之后,打开另一个命令提示符窗口,运行这个命令来打开一个隧道到5000端口。

ngrok http 5000

之后,你的命令提示符应该看起来像这样。

Running ngrok in the command prompt, a list of session statuses is displayed, including a forwarding URL.

Forwarding这个词的旁边,应该有一个指向https://localhost:5000URL*。*你的URL应该与上面显示的不同。复制该URL,因为它将被用于设置网络钩子。让这个命令提示符打开。

在你的Twilio控制台的左侧,导航到电话号码>管理>活动号码。点击活动号码将带你到活动号码页面。点击你将在此应用中使用的电话号码的链接。

这将带你到该电话号码的配置页面。向下滚动到 "消息",将你之前复制的URL粘贴到 "消息"部分,并在URL的末尾添加"/分析"。所以你的URL应该是类似于*your-ngrok-url.ngrok.io/analyze*,并且…

Twilio Phone Number configuration form where the phone number is configured to send text messages to a webhook with the ngrok Forwarding URL.

点击页面底部的 "保存"来更新号码的设置。现在你终于准备好运行该应用程序了。

运行应用程序

要运行该应用程序,请在终端运行该命令。

flask run

如果你使用的是macOS,如果你还没有安装证书,可能会出现SSL证书验证错误。如果是这样,点击进入你在应用程序文件夹中使用的Python版本,并点击安装证书.命令。再次运行你的应用程序。

之后,你的应用程序应该可以正常工作了。给Twilio的电话号码发一个搜索查询短信,应该会有回复出现。

SMS conversation where "hello world" was sent and polarity scores and keywords related to "hello world" was responded with.

SMS conversation with one participant sending an emojis and the other responding with polarity scores and keywords calculated from the emoji.

总结

恭喜你用Twilio SMS建立了一个应用程序。你的应用程序不仅能接收短信,而且还能分析文本的情感,并将分析的结果回复。你可以在这个应用程序中自由发挥你的想象力。可能性包括(但不限于)将网址改为不同的网站,而不是城市词典,为应用程序添加更多的功能,以及与其他人分享这个应用程序。

对使用Twilio和Python构建更多的功能感到兴奋吗?看看下面的资源,了解更多。

Johnny Nguyen是Twilio开发者之声团队的一名实习开发者。他喜欢创造讽刺性的编码项目,让别人学习和享受。当他没有打盹或看TikTok时,可以通过ngnguyen [at] twilio.com联系他。