用NodeJS進行Twitter情感分析
如果你想知道大家對某件事情的看法,Twitter 是最好的地方了。Twitter 是觀點持續(xù)不斷的涌現(xiàn)出來的地方,每秒鐘大概有 6000 條新 Twitter 發(fā)送出來。因特網(wǎng)上的發(fā)展很快,如果你想與時俱進或者跟上潮流,Twitter 就是你要去的地方。
現(xiàn)在,我們生活在一個數(shù)據(jù)為王的時代,很多公司都善于運用 Twitter 上的數(shù)據(jù)。根據(jù)測量到的他們新產(chǎn)品的人氣,嘗試預(yù)測之后的市場趨勢,分析 Twitter 上的數(shù)據(jù)有很多用處。通過數(shù)據(jù),商人把產(chǎn)品賣給合適的用戶,收集關(guān)于他們品牌和改進的反饋,或者獲取他們產(chǎn)品或促銷活動失敗的原因。不僅僅是商人,很多政治和經(jīng)濟上的決定是在觀察人們意見的基礎(chǔ)上所作的。今天,我會試著讓你感受下關(guān)于 Twitter 的簡單 情感分析,判斷這個 Twitter 是正能量、負(fù)能量還是中性的。這不會像專業(yè)人士所用的那么復(fù)雜,但至少,它會讓你知道挖掘觀念的想法。
我們將使用 NodeJs,因為 JavaScript 太常用了,而且它還是最容易入門的語言。
前置條件:
- 安裝了 NodeJs 和 NPM
- 有 NodeJs 和 NPM 包的經(jīng)驗
- 熟悉命令行。
好了,就是這樣。開始吧。
開始
為了你的項目新建一個目錄,進入這個目錄下面。打開終端(或是命令行)。進入剛創(chuàng)建的目錄下面,運行命令 npm init -y。這會在這個目錄下創(chuàng)建一個 package.json 文件。現(xiàn)在我們可以安裝需要的 npm 包了。只需要創(chuàng)建一個新文件,命名為 index.js 然后我們就完成了初始的編碼。
獲取推文
好了,我們想要分析 Twitter ,為了實現(xiàn)這個目的,我們需要以編程的方式訪問 Twitter。為此,我們要用到 twit 包。因此,先用 npm i wit 命令安裝它。我們還需要注冊一個 App,以通過我們的賬戶來訪問 Twitter 的 API。點擊這個 鏈接,填寫所有項目,從 “Keys and Access Token” 標(biāo)簽頁中復(fù)制 “Consumer Key”、“Consumer Secret”、“Access token” 和 “Access Token Secret” 這幾項到一個 .env 文件中,就像這樣:
# .env# replace the stars with values you copiedCONSUMER_KEY=************CONSUMER_SECRET=************ACCESS_TOKEN=************ACCESS_TOKEN_SECRET=************
現(xiàn)在開始。
用你最喜歡的代碼編輯器打開 index.js。我們需要用 npm i dotenv 命令安裝 dotenv 包來讀取 .env 文件。好了,創(chuàng)建一個 API 實例。
const Twit = require('twit');const dotenv = require('dotenv');dotenv.config();const { CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET} = process.env;const config_twitter = {consumer_key: CONSUMER_KEY,consumer_secret: CONSUMER_SECRET,access_token: ACCESS_TOKEN,access_token_secret: ACCESS_TOKEN_SECRET,timeout_ms: 60*1000};let api = new Twit(config_twitter);
這里已經(jīng)用所需的配置文件建立了到 Twitter 上的連接。但我們什么事情都沒做。先定義個獲取推文的函數(shù):
async function get_tweets(q, count) {let tweets = await api.get('search/tweets', {q, count, tweet_mode: 'extended'});return tweets.data.statuses.map(tweet => tweet.full_text);}
這是個 async 函數(shù),因為 api.get 函數(shù)返回一個 promise 對象,而不是 then 鏈,我想通過這種簡單的方式獲取推文。它接收兩個參數(shù) q 和 count,q 是查詢或者我們想要搜索的關(guān)鍵字,count 是讓這個 api 返回的推文數(shù)量。
目前為止我們擁有了一個從 Twitter 上獲取完整文本的簡單方法。不過這里有個問題,現(xiàn)在我們要獲取的文本中可能包含某些連接或者由于轉(zhuǎn)推而被截斷了。所以我們會編寫另一個函數(shù),拆解并返回推文的文本,即便是轉(zhuǎn)發(fā)的推文,并且其中有鏈接的話就刪除。
function get_text(tweet) {let txt = tweet.retweeted_status ? tweet.retweeted_status.full_text : tweet.full_text;return txt.split(/ |\n/).filter(v => !v.startsWith('http')).join(' ');}async function get_tweets(q, count) {let tweets = await api.get('search/tweets', {q, count, 'tweet_mode': 'extended'});return tweets.data.statuses.map(get_text);}
現(xiàn)在我們拿到了文本。下一步是從文本中獲取情感。為此我們會使用 npm 中的另一個包 —— sentiment。讓我們像安裝其他包那樣安裝 sentiment,添加到腳本中。
const sentiment = require('sentiment')
sentiment 用起來很簡單。我們只用把 sentiment 函數(shù)用在我們想要分析的文本上,它就能返回文本的相對分?jǐn)?shù)。如果分?jǐn)?shù)小于 0,它表達的就是消極情感,大于 0 的分?jǐn)?shù)是積極情感,而 0,如你所料,表示中性的情感?;诖?,我們將會把推文打印成不同的顏色 —— 綠色表示積極,紅色表示消極,藍(lán)色表示中性。為此,我們會用到 colors 包。先安裝這個包,然后添加到腳本中。
const colors = require('colors/safe');
好了,現(xiàn)在把所有東西都整合到 main 函數(shù)中。
async function main() {let keyword = \* define the keyword that you want to search for *\;let count = \* define the count of tweets you want *\;let tweets = await get_tweets(keyword, count);for (tweet of tweets) {let score = sentiment(tweet).comparative;tweet = `${tweet}\n`;if (score > 0) {tweet = colors.green(tweet);} else if (score < 0) {tweet = colors.red(tweet);} else {tweet = colors.blue(tweet);}console.log(tweet);}}
最后,執(zhí)行 main 函數(shù)。
main();
就是這樣,一個簡單的分析推文中的基本情感的腳本。
\\ full scriptconst Twit = require('twit');const dotenv = require('dotenv');const sentiment = require('sentiment');const colors = require('colors/safe');dotenv.config();const { CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET} = process.env;const config_twitter = {consumer_key: CONSUMER_KEY,consumer_secret: CONSUMER_SECRET,access_token: ACCESS_TOKEN,access_token_secret: ACCESS_TOKEN_SECRET,timeout_ms: 60*1000};let api = new Twit(config_twitter);function get_text(tweet) {let txt = tweet.retweeted_status ? tweet.retweeted_status.full_text : tweet.full_text;return txt.split(/ |\n/).filter(v => !v.startsWith('http')).join(' ');}async function get_tweets(q, count) {let tweets = await api.get('search/tweets', {q, count, 'tweet_mode': 'extended'});return tweets.data.statuses.map(get_text);}async function main() {let keyword = 'avengers';let count = 100;let tweets = await get_tweets(keyword, count);for (tweet of tweets) {let score = sentiment(tweet).comparative;tweet = `${tweet}\n`;if (score > 0) {tweet = colors.green(tweet);} else if (score < 0) {tweet = colors.red(tweet);} else {tweet = colors.blue(tweet)}console.log(tweet)}}main();























