Coder Social home page Coder Social logo

minoue-xx / tweet-with-wordcloud Goto Github PK

View Code? Open in Web Editor NEW
0.0 3.0 0.0 14.54 MB

This repo provides MATLAB and Python codes that tweet a word cloud image generated from the MATLAB/Simulink-related tweet texts in Japanese over the past 7 days. The code execution is intended to be automated by GitHub Actions.

License: MIT License

Python 100.00%

tweet-with-wordcloud's Introduction

Tweet のワードクラウド作成からツイートまで

Copyright (c) 2022 Michio Inoue.

まずは Tweet の取得

Tweet の取得については Conduct Sentiment Analysis Using Historical Tweets がピンポイントの例題としてあるので、こちらを参照します。

ただそのまま使うと省略された Tweet 本文になっちゃうので 'tweet_mode''extended' にしておくことを忘れずに!

% settokens % Twitter API の利用申請は別途必要(ここでは各種 API キーは環境変数として設定しているとします。)
consumerkey = getenv("CONSUMERKEY");
consumersecret = getenv("CONSUMERSECRET");
accesstoken = getenv("ACCESSTOKEN");
accesstokensecret = getenv("ACCESSTOKENSECRET");

Twitter オブジェクトの作成(Datafeed Toolbox)

c = twitter(consumerkey,consumersecret,accesstoken,accesstokensecret);
c.StatusCode
ans = 
  StatusCode の列挙値

    OK

OK ということで無事繋がりました。search 関数で Tweet の検索結果をとってきます。試しに 100 Tweets とってみます。

tweetquery = '"MATLAB" OR "Simulink" lang:ja';
s = search(c,tweetquery,'count',100,'tweet_mode','extended');

statuses に Tweet の情報が入ります。1 Tweet = 1 構造体で取得されるので、今回の呼び出しだと 100x1 のセル配列として返ってきます。

statuses = s.Body.Data.statuses;
whos statuses
  Name            Size              Bytes  Class    Attributes

  statuses      100x1             2581021  cell               

search 関数では Twitter API 仕様上最新の 7 日間の Tweet までしか遡れないことに注意。

また、一度の call で最大 100 Tweet しか取れませんので、繰り返し呼び出す必要があります。'max_id' でどこから先のデータを取得するかを指定します。

% Retrieve All Available Tweets
while isfield(s.Body.Data.search_metadata,'next_results')
    % Convert results to string
    nextresults = string(s.Body.Data.search_metadata.next_results);
    % Extract maximum Tweet identifier
    max_id = extractBetween(nextresults,"max_id=","&");
    % Convert maximum Tweet identifier to a character vector
    cmax_id = char(max_id);
    % Search for Tweets
    s = search(c,tweetquery,'count',100,'max_id',cmax_id,'tweet_mode','extended');
    % Retrieve Tweet text for each Tweet
    statuses = [statuses;s.Body.Data.statuses];
end
length(statuses)
ans = 700

Tweet が取れてますね。

timetable 型にまとめる

全部取れたら構造体から必要な情報だけ取り出しておきます。ここでは Tweet された時刻(created_at)と Tweet 本文(full_text)です。

if iscell(statuses)
    % Unstructured data
    numTweets = length(statuses);             % Determine total number of Tweets
    tweetTimes = cell(numTweets,1);           % Allocate space for Tweet times and Tweet text
    tweetTexts = tweetTimes;
    tweetUsers = tweetTimes;
    tweetSources = tweetTimes;
    for i = 1:numTweets
        tweetTimes{i} = statuses{i}.created_at; % Retrieve the time each Tweet was created
        tweetTexts{i} = statuses{i}.full_text;       % Retrieve the text of each Tweet
        tweetUsers{i} = statuses{i}.user.name;
        tweetSources{i} = statuses{i}.source;
    end
else
    % Structured data
    tweetTimes = {statuses.created_at}';
    tweetTexts = {statuses.text}';
    tweetUsers = {statuses.user.name}';
    tweetSources = {statuses.source}';
end
tweetSources = extractHTMLText(tweetSources);

お馴染みの timetable 型にまとめておきます。時刻データのフォーマットに要注意。

tweetTimes{1}
ans = 'Mon Jun 13 17:53:02 +0000 2022'

こんな形で入っています。datetime 型に変換する場合は 'Locale''en_US' に設定することをお忘れなく。

tweets = timetable(tweetTexts,tweetUsers,tweetSources,'RowTimes', ...
    datetime(tweetTimes,'Format','eee MMM dd HH:mm:ss +SSSS yyyy','Locale','en_US'));

Tweet 時刻は +0000 と出ていることから分かるように UTC なので、東京時間に合わせておきます。datetime 型の TimeZone を UTC に設定後、Asia/Tokyo に変えるだけ。

tweets.Time.TimeZone = 'UTC';
tweets.Time.TimeZone = 'Asia/Tokyo';
tweets.Time.Format = 'yyyy/MM/dd HH:mm:ss';
% save('tweets20220531.mat','tweets','statuses')

これで完成。データは保存しておきます。

ワードクラウド

このワードクラウドは文字列をそのまま入れているので MATLAB 本体の wordcloud 関数です。

wordcloud(tweets.tweetTexts)

figure_0.png

せっかくなのでちょっと細かい前処理を

上のワードクラウドを見るといくつか気になる点があります。

  • matlab や MATLAB など大文字小文字の揺らぎ
  • RT?
  • @ によるメンション

この辺を処理します。

まず RT。これは Retweet された Tweet が例えば RT @michio_MWJ: ではじまることから登場回数が多くなります。この辺はアカウント名も含めて取り除いておきます。

% load tweets20220614.mat
tweets.tweetTexts = string(tweets.tweetTexts);

wildcardPattern を使って RT @[アカウント名]: ではじまる Tweet を探して、対象の者は extractAfter でその後に続く本文だけを残す処理にします。

pat = "RT @" + wildcardPattern("Except",":") + (":");
idx = contains(tweets.tweetTexts,pat);
tweets.tweetTexts(idx) = extractAfter(tweets.tweetTexts(idx),pat);

次に大文字小文字の揺らぎ。これは lower や upper を使って小文字か大文字に揃えてもよいのですが、ここでは caseInsensitivePattern を使って大文字小文字関係なく検索した上で、特定の文字に置き換える処理をしてみます。

pat = caseInsensitivePattern("MATLAB"); % Matlab, matlab, matLAB も検索対象
tweets.tweetTexts = replace(tweets.tweetTexts,pat,"MATLAB"); % すべて MATLAB に

今回特に見えていませんが、画像の URL も邪魔ではあります。これは alphanumericsPattern で一掃します。

pat = "https://t.co/" + alphanumericsPattern;
tweets.tweetTexts = replace(tweets.tweetTexts,pat,"");

そして再度ワードクラウド。ちょっと綺麗になったかな。タイトル付けて保存します。

figure
wordcloud(tweets.tweetTexts)
title("What people say about MATLAB and Simulink?")
exportgraphics(gcf,"wordcloud_weekly.png");

figure_1.png

Tweepy を使って Tweet します。

text = "過去 7 日間の MATLAB/Simulink 関連ツイートのワードクラウド (Tweeted from GitHub Actions)";
py.tweetImage.tweetWithImage(text,'wordcloud_weekly.png')

おまけ:もう少しだけ深掘り

いろいろ気になってきたのでもうちょっと深掘りしてみよう。

ここからは Text Analytics Toolbox を使って品詞(PartOfSpeech)を気にしてみます。MATLAB Expo であることは分かり切っているので関連ワードも削除しておきます。

doc = tokenizedDocument(tweets.tweetTexts); % トークン化
doc = removeWords(doc,["#MATLAB","MATLAB","Simulink"]);
tdetails = tokenDetails(doc);
head(tdetails)
Token DocumentNumber LineNumber Type Language PartOfSpeech Lemma Entity
1 "Mac" 1 1 letters ja other "Mac" non-entity
2 "で" 1 1 letters ja adposition "で" non-entity
3 "レポンヨヨ" 1 1 letters ja noun "レポンヨヨ" non-entity
4 "書" 1 1 letters ja noun "書" non-entity
5 "か" 1 1 letters ja adposition "か" non-entity
6 "なあ" 1 1 letters ja adposition "なあ" non-entity
7 "かんし" 1 1 letters ja noun "かんし" non-entity
8 "Linux" 1 1 letters ja other "Linux" non-entity

adposition(接置詞)や auxiliary-verb (助動詞)は情報量少なそうなのでいらいですね。

idx = tdetails.PartOfSpeech == "adposition" | tdetails.PartOfSpeech == "auxiliary-verb";
words2display = tdetails(~idx,"Token");
wordcloud(words2display.Token)

figure_2.png

なんだか「できる!」気がする前向きな感じが出てきました。

最後に品詞別に副詞(adverb)、形容詞(adjective)、名詞(noun)、動詞(verb)を見てみます。

lists = ["adverb","adjective","noun","verb"];
t = tiledlayout('flow','TileSpacing','compact');

for parts = lists
    nexttile;
    idx = tdetails.PartOfSpeech == parts;
    words = tdetails(idx,"Token");
    wordcloud(words.Token);
    title(parts);
end

figure_3.png

tweet-with-wordcloud's People

Contributors

minoue-xx avatar

Watchers

 avatar James Cloos avatar Kostas Georgiou avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.