Node.js 如何创建情感分析应用程序
情感分析是一种自然语言处理技术,用于确定文本数据中的情绪。它通常用于了解客户需求、研究用户反馈中的产品情绪、决策等。
情感分析的类型:
- 细粒度情感分析: 当我们希望在结果中获得极性精度时使用。在这种类型的分析中,我们将结果分为非常消极、消极、积极、非常积极和中性等极性类别。
- 基于情感的情感分析: 此类型的分析检测到不同类型的情感,如快乐、愤怒和悲伤。
- 基于方面的情感分析: 如果我们想要知道用户以正面或负面方式提及的特定方面或特征,那么就会使用这种类型的分析。例如,用户评论说这台笔记本电脑非常好,但是电池非常差,所以我们的基于方面的算法将能够确定有关电池的负面意见,而不是整个产品。
方法: 本文中,我们将使用Node.js创建一个情感分析应用程序,该应用程序分析用户反馈中的文本数据,并结合细粒度和基于情感的情感分析方法来获取用户情感。我们将使用AFINN(用于赋予英文单词价值的字典,值为介于负五(负面)到正五(正面)之间的整数),该字典包含在我们将在应用程序中包含为npm软件包的自然语言处理库中。
下面是逐步实施的步骤:
安装Node.js: 请访问以下链接下载并安装Node.js:下载Node.js。我们将通过执行以下命令来确保我们的系统中安装了Node:
步骤1: 创建一个单独的文件夹,并使用终端或命令提示符导航到该文件夹并进入该文件夹。
步骤2: 在终端中输入以下命令来创建 package.json:
步骤3: 安装以下依赖项。
- Express: Express是一个简洁灵活的Node.js Web应用程序框架,为Web和移动应用程序提供强大的功能集
- Natural: 一个支持大多数NLP算法的Node.js软件包
- Stopword: 一个允许您从输入文本中删除停用词的Node.js软件包
项目结构: 项目结构将如下所示:

步骤4: 首先,我们将创建一个基本的HTTP服务器。
server.js
步骤5: 创建一个新的路由并将其路径设置为 /feedback。 当用户将反馈内容包含在请求体中通过 POST 请求发送到我们的路由时,他们应该收到一个包含其情感分析的响应。
server.js
步骤6: 我们从用户那里得到的数据充斥着许多错误和噪音,我们需要在分析过程中对其进行过滤。为了提取有意义的情感或信息,我们需要对用户的文本数据进行筛选,这个过程叫做数据过滤。
过滤步骤:
- 为了保持数据的结构,我们将所有单词转换为标准形式。例如,You’re -> You are。
- 所有文本数据将被转换为小写形式,因为我们希望我们的分析算法将brilliant和BriLLiaNt视为相同单词。
- 删除特殊字符和数值标记,因为它们只是噪音元素,对我们的结果的贡献将为零。
- 分词是过滤过程中的关键步骤之一,这是将文本拆分为有意义单元的过程。我们将使用我们引入的Natural包中的WordTokenizer。
- 删除停用词,因为这些词对用户的情感没有任何贡献,一些停用词的示例包括:but, a, or,等等。
- NLP中的单词归一化过程中,预计使用词干算法将单词减少为其根词。例如,“training”,“trained”变为“train”。调用时,Natural库中的Sentiment Analyzer可以提供词干器作为参数。在分析过程中,个别单词将被转换为其根本形式。
使用Natural进行情感分析: Natural库中的情感分析算法使用了一个评分的英语词汇表AFINN,该词汇表以介于负五(消极)和正五(积极)之间的整数对英语单词进行了评估。算法运作方式是计算一个文本中每个词的极性的总和,并将其与句子长度归一化。如果算法返回一个负值,那意味着情感是消极的,如果返回一个正值,则意味着情感是积极的。零值表示中性情绪。
我们将创建一个名为/feedback的路由,用于收集用户的反馈并实现我们的分析。名为convertToStandard的函数将把我们的所有数据转换为标准形式。convertTolowerCase函数将把我们的所有数据转换为小写形式。removeNonAlpha函数将删除非字母字符。接下来,我们将使用stopword npm包对我们的数据进行分词和删除停用词。在进行所有这些数据过滤的代码之后,我们将使用Natural包中的SentimentAnalyzer创建一个情感评分。最后,我们将根据我们的分析将这个情感评分作为回应发送给我们的用户。
server.js文件
const express = require("express");
const natural = require("natural");
const stopword = require("stopword");
const wordDict = {
"aren't": "are not",
"can't": "cannot",
"couldn't": "could not",
"didn't": "did not",
"doesn't": "does not",
"don't": "do not",
"hadn't": "had not",
"hasn't": "has not",
"haven't": "have not",
"he'd": "he would",
"he'll": "he will",
"he's": "he is",
"i'd": "I would",
"i'd": "I had",
"i'll": "I will",
"i'm": "I am",
"isn't": "is not",
"it's": "it is",
"it'll": "it will",
"i've": "I have",
"let's": "let us",
"mightn't": "might not",
"mustn't": "must not",
"shan't": "shall not",
"she'd": "she would",
"she'll": "she will",
"she's": "she is",
"shouldn't": "should not",
"that's": "that is",
"there's": "there is",
"they'd": "they would",
"they'll": "they will",
"they're": "they are",
"they've": "they have",
"we'd": "we would",
"we're": "we are",
"weren't": "were not",
"we've": "we have",
"what'll": "what will",
"what're": "what are",
"what's": "what is",
"what've": "what have",
"where's": "where is",
"who'd": "who would",
"who'll": "who will",
"who're": "who are",
"who's": "who is",
"who've": "who have",
"won't": "will not",
"wouldn't": "would not",
"you'd": "you would",
"you'll": "you will",
"you're": "you are",
"you've": "you have",
"'re": " are",
"wasn't": "was not",
"we'll": " will",
"didn't": "did not"
}
const port = 5500;
const host = "127.0.0.1";
let app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/",express.static(__dirname + "/public"));
const convertToStandard = text => {
const data = text.split(' ');
data.forEach((word, index) => {
Object.keys(wordDict).forEach(key => {
if (key === word.toLowerCase()) {
data[index] = wordDict[key]
};
});
});
return data.join(' ');
}
const convertTolowerCase = text => {
return text.toLowerCase();
}
const removeNonAlpha = text => {
return text.replace(/[^a-zA-Z\s]+/g, '');
}
app.post("/feedback", (request, response) => {
console.log(request.body);
const lexData = convertToStandard(request.body.feedback);
console.log("Lexed Data: ",lexData);
const lowerCaseData = convertTolowerCase(lexData);
console.log("LowerCase Format: ",lowerCaseData);
const onlyAlpha = removeNonAlpha(lowerCaseData);
console.log("OnlyAlpha: ",onlyAlpha);
const tokenConstructor = new natural.WordTokenizer();
const tokenizedData = tokenConstructor.tokenize(onlyAlpha);
console.log("Tokenized Data: ",tokenizedData);
const filteredData = stopword.removeStopwords(tokenizedData);
console.log("After removing stopwords: ",filteredData);
const Sentianalyzer =
new natural.SentimentAnalyzer('English', natural.PorterStemmer, 'afinn');
const analysis_score = Sentianalyzer.getSentiment(filteredData);
console.log("Sentiment Score: ",analysis_score);
response.status(200).json({
message: "Data received",
sentiment_score: analysis_score
})
});
app.listen(port, host, () => {
console.log('Server is running...');
});
步骤7: 为了将前端与我们的服务器连接起来,我们需要在我们的server.js文件中添加一行代码,这意味着我们的所有静态HTML,CSS和JS文件将被提供在/路由下。
server.js
现在,我们将创建一个名为index.html的HTML文件,该文件将成为我们的前端页面。
index.html
步骤8:
现在在/public文件夹中,让我们创建一个名为main.js的文件,在其中我们将添加一些用于进行API调用的函数。获取所有的HTML元素。所以我们的逻辑是,当用户填写反馈表单后,在点击提交按钮后,应该调用一个函数并向我们的node js服务器发出API调用。我们将在按钮上添加一个点击事件,在点击时,我们将向服务器发出API调用,并根据我们的反馈获取响应。根据我们的情感评分,我们将用表情符号显示结果。
main.js
运行该应用的步骤: 要启动此应用程序,请在命令提示符上执行以下命令:
输出:
Navigate to
http://localhost:5500/

服务器日志:
