MATLAB ユーザーコミュニティー

MATLAB & Simulink ユーザーコミュニティー向け日本語ブログ

MATLAB Answers:日本語の質問に回答してくれているのはどなた?

「MATLAB Answers に回答くださっている皆様、本当にありがとうございます。」
こんにちは、井上です。最近オンラインミーティング用に遅ればせながら女優ライトを導入しました。思いのほかまぶしいので、ここぞ!というときに活用しようと思います。

さて、MATLAB 関連の質問をするなら MATLAB Answers ですが、ここではどんな人が回答してくれているんだろう。MATLAB Answers 全体のランキングは用意されているんですが、日本語の質問に絞ると・・?
ということで日本語の質問に応えてくれている方を探し出し、 Twitter @JPMATLABAnswers からこっそり感謝を伝えてみることにしました。今回はこの全工程をご紹介いたします。見どころは Twitter Bot 化する為の ThingSpeak x GitHub Actions の連携です!コードは GitHub: who-are-the-contributors-on-MATLAB-answers-in-japanese に公開しています。

Hernia Baby さんと Atsushi Ueno さんには以前 blog にも登場して頂いてますね!


まずは現状確認

MATLAB Answers の UI を確認します。

貢献度ランキング

キャプチャ.PNG
週間、月間、年間の貢献度ランキングがあります。ちなみにこの “評価” という数字は
  • 自分の回答が採用される:4 ポイント
  • 自分の回答に投票される:2 ポイント
  • 自分の質問に投票される:1 ポイント
という形で数値化されてまして、ポイントがたまると質問、回答、およびコメントの編集や削除などもできるようになります。詳細はこちらにあります。

日本語への回答者は?

残念ながら上のランキングでは日本語の質問に回答してくれているかどうかを判別することはできません。そもそも日本語と英語両方に回答している場合考えると日本語フィルタ―は現実的ではないですね。

質問ページを調査する

質問ページを見てみます。こちらには日本語フィルタがありますね。そして MathWorks Support フィルタ。これは公式サポートチームが FAQ として公開しているものをさします。それ以外のポストはすべて ”コミュニティ” になります。
キャプチャ.PNG
各ページには〇〇さんによって質問された、◇◇さんが回答したなどの情報があるので、これを吸い上げればいいかもしれません。


それでどうしたか?

  1. 一定期間内に更新された日本語の質問ページを抽出
  2. それらに関わるアカウント名を集計
  3. ランキング上位者を見つける
  4. Twitter で呟く
  5. GitHub Actions で定期実行
こんな感じですね。例えば週間ランキングであれば、過去1週間に更新のあった(すなわち回答やコメントが付いた)ページを対象にすればいいですね。
href=”/matlabcentral/profile/authors/2229289″>Keisuke Miura</a>
href=”/matlabcentral/profile/authors/14080697″>Misa Taguchi</a>
と Keisuke Miura さんと Misa Taguchi さんの名前が出てきます。これを正規表現を使って抽出できそうです。まずは1から順番に。

1. 一定期間内に更新された日本語の質問ページを抽出

日本語・コミュニティの 2 つのフィルターを適用したページを開きます。「このビューを購読」すると RSS フィードが確認できます。RSS(RDF Site Summary/Rich Site Summary)はデータ形式の一種で、Webサイト内の新着ページや更新ページのタイトルや URL、更新日時、要約などを一覧形式で取得できるので便利。
キャプチャ.PNG
XML 形式になっていますので、xmlread 関数を使います。
xDoc = xmlread([‘https://jp.mathworks.com/matlabcentral/answers’
‘/questions?language=ja&format=atom&sort=updated+desc&status=answered’
‘&page=1’]);
MATLAB Answers の場合は 1 ページあたり 50 個しか情報が含まれないので、page=1 とページ番号を振って過去にさかのぼっていくことになります。欲しい情報だけを取り出していきますが、XML 形式は中身の確認が面倒・・欲しい情報がどこに隠れているかを地道に探っていきます。
% まず各投稿は <entry></entry>
allListitems = xDoc.getElementsByTagName(‘entry’);
% アイテム数だけ配列を確保
title = strings(allListitems.getLength,1); % タイトル
url = strings(allListitems.getLength,1); % URL
author = strings(allListitems.getLength,1); % 投稿者
updated = strings(allListitems.getLength,1); % 最終更新日時
% 各アイテムから title, url, author 情報を出します。
for k = 0:allListitems.getLength-1
thisListitem = allListitems.item(k);
% Get the title element
thisList = thisListitem.getElementsByTagName(‘title’);
thisElement = thisList.item(0);
% The text is in the first child node.
title(k+1) = string(thisElement.getFirstChild.getData);
% Get the link element
thisList = thisListitem.getElementsByTagName(‘link’);
thisElement = thisList.item(0);
% The url is one of the attributes
url(k+1) = string(thisElement.getAttributes.item(0));
% Get the author element
thisList = thisListitem.getElementsByTagName(‘author’);
thisElement = thisList.item(0);
childNodes = thisElement.getChildNodes;
author(k+1) = string(childNodes.item(1).getFirstChild.getData);
% Get the <updated>2020-04-18T16:40:12Z</updated>
thisList = thisListitem.getElementsByTagName(‘updated’);
thisElement = thisList.item(0);
updated(k+1) = string(thisElement.getFirstChild.getData);
end
% 日時データは datetime 型に変換しておきます。
updated_at = datetime(updated,‘InputFormat’, “uuuu-MM-dd’T’HH:mm:ss’Z”);
updated_at.Format = ‘uuuu-MM-dd HH:mm:ss’;
% URL は以下の形になっているので、
% href=”https://www.mathworks.com/matlabcentral/answers/477845-bode-simulink-360″
url = extractBetween(url,“href=”””,“”””); % URL 部分だけ取得
entryID = double(extractBetween(url,“answers/”,“-“)); % 投稿IDを別途確保
ここまでの情報をテーブルにまとめると以下の通り。
pagelist = timetable(title, url, author, ‘RowTimes’, updated_at,
‘VariableNames’,{‘titles’, ‘urls’, ‘authors’})
pagelist = 50×3 timetable
Time titles urls authors
1 2022-04-18 09:34:24 “Busのデータを算出しているサブシステム以外のサブシステムでデータ書き換えをする方法をご教示いただきたい。” “https://www.mathworks.com/matlabcentral/answers/1698985-bus” “利元 河合”
2 2022-04-18 07:27:38 “OpenPoseを用いた深層学習を使用した体の姿勢の推定の例で画像ではなく,動画ファイルにおける人の姿勢の推定を行う方法について” “https://www.mathworks.com/matlabcentral/answers/1696285-openpose” “WH”
3 2022-04-15 05:40:26 “yyaxis関数使用時にy軸の色が変えられない” “https://www.mathworks.com/matlabcentral/answers/1696965-yyaxis-y” “佳琳 杉浦”
4 2022-04-15 01:11:08 “2つ以上の同じ要素を持つ列を削除” “https://www.mathworks.com/matlabcentral/answers/1696465-“ “NK”
5 2022-04-15 01:09:57 “マスクでの入力値を他ブロックの入力に反映させる方法” “https://www.mathworks.com/matlabcentral/answers/1694450-“ “kkdra57”
6 2022-04-14 09:00:13 “License Manager Error -16 が発生するのはなぜですか?” “https://www.mathworks.com/matlabcentral/answers/98578-license-manager-error-16” “MathWorks Support Team”
7 2022-04-14 07:03:35 “MATLAB 学生向けライセンスまたはMATLAB Home ライセンスの領収書発行方法を教えてください。” “https://www.mathworks.com/matlabcentral/answers/346697-matlab-matlab-home” “MathWorks Support Team”
8 2022-04-14 06:45:38 “任意の信号波形の作成方法が分からない” “https://www.mathworks.com/matlabcentral/answers/1693385-“ “takaaki yamada”
9 2022-04-13 09:16:26 “フレームベースのデータの表示(シミュレーションデータインスペクター)” “https://www.mathworks.com/matlabcentral/answers/1695400-“ “kkdra57”
10 2022-04-13 06:33:32 “それぞれのboxplotに平均値をplotする+それぞれのboxplotの外れ値の色を変える” “https://www.mathworks.com/matlabcentral/answers/1689845-boxplot-plot-boxplot” “Raki Kawama”
11 2022-04-13 05:26:46 “signal tool boxのlowpassについて” “https://www.mathworks.com/matlabcentral/answers/1691655-signal-tool-box-lowpass” “mushi77”
12 2022-04-13 05:16:08 “ライセンスにラベルを追加するにはどうすればよいですか?” “https://www.mathworks.com/matlabcentral/answers/1693600-“ “MathWorks Support Team”
13 2022-04-13 04:48:27 “ライセンス センターをどのように使いますか?” “https://www.mathworks.com/matlabcentral/answers/94339-“ “MathWorks Support Team”
14 2022-04-12 23:59:58 “MATLAB Compiler (SDK) で LogicAnalyzer を動かそうと思っても、名前dsp.LogicAnalyzerを解決できません のエラーになる” “https://www.mathworks.com/matlabcentral/answers/1693675-matlab-compiler-sdk-logicanalyzer-dsp-logicanalyzer” “久之助 三宅”
イイ感じです。
次は各ページでに関連するユーザーアカウントを探してくる作業を行います。

2. それらに関わるアカウント名を集計

例として1つ目の質問を見てみましょう。
名前は
href=“/matlabcentral/profile/authors/14080697”>Misa Taguchi</a>
と出ているはずなので、正規表現は
regexp(txt,‘href=”/matlabcentral/profile/authors/(?:\d+?)”>([^<].+?)</a>’,‘tokens’);
で行けるはず。
url = pagelist.urls(1)
url = “https://www.mathworks.com/matlabcentral/answers/1698985-bus”
txt = webread(url);
users_on_post = regexp(txt,‘href=”/matlabcentral/profile/authors/(?:\d+?)”>([^<].+?)</a>’,‘tokens’);
string(users_on_post)’
ans = 3×1 string
“利元 河合”
“Toshinobu Shi…
“Toshinobu Shi…
イイ感じ。2 回登場していますが、これは unique 関数を噛ましておけばOKでしょう。
上で抽出したページに対して回すことで、最近アップデートのあった日本語ページに登場するアカウント名を取り出します。
item2check = pagelist;
users = [];
for ii=1:height(item2check)
url = item2check.urls(ii);
txt = webread(url);
% href=”/matlabcentral/profile/authors/6704456″>Atsushi Ueno</a>
users_on_post = regexp(txt,‘href=”/matlabcentral/profile/authors/(?:\d+?)”>([^<].+?)</a>’,‘tokens’);
users = [users, string(users_on_post)];
end
% unique account
nicknames = unique(users);
idx = nicknames == “MathWorks Support Team”; % サポートチームは除いておきます。
nicknames(idx) = [];
nicknames(1:5)’
ans = 5×1 string
“Akira Agata”
“Atsushi Ueno”
“Hernia Baby”
“Hiroki Takeda”
“Hiroyuki His…
取れていますね。

3. ランキング上位者を見つける

例えば週間ランキングページの URL は
baseURL = “https://jp.mathworks.com/matlabcentral/answers/contributors/?filter=week”;
こんな様子です。これも各ページ 50 人の表示なので、それ以上の情報をとる場合は page を使います。
試しに上位 250 人を抽出するならこんな感じ。HTML ファイルをいじるなら webread 関数からの htmlTree 関数。これは Text Analytics Toolbox が必要ですが、要素を抽出するのに便利です。がんばれば正規表現で対応できそうですけども。
この辺は HTML のソースとにらめっこしながら欲しい情報がどこにあるか調べながらコードに落とし込みます。
perpage = 50; % ページ当たりの人数
pages = 1; % 5 ページ確認します(合計 250 人)
ranks = zeros(perpage*pages,1);
names = strings(perpage*pages,1);
for ii=1:pages
url = baseURL + “&page=” + ii;
a = webread(url);
b = htmlTree(a);
c = findElement(b,“td:first-child”);
for jj=1:perpage
index = (ii-1)*perpage+jj;
% 順位
tmp = findElement(c(jj),“div:first-child”);
ranks(index) = extractHTMLText(tmp);
% アカウント名
tmp = findElement(c(jj),“H4 > A > SPAN”);
names(index) = extractHTMLText(tmp);
end
end
names
names = 50×1 string
“_”
“Image Analyst”
“Walter Roberson”
“MathWorks Support …
“Star Strider”
“Torsten”
“Matt J”
“KSSV”
“DGM”
“Sam Chak”
錚々たる面子です。
この中から、上で探し出してきた日本語の質問に関連するユーザーアカウントを ismember 関数で抽出します。
idx = ismember(names,nicknames);
dataset = table(ranks(idx),names(idx),‘VariableNames’,{‘rank’,‘nickname’})
dataset = 2×2 table
rank nickname
1 37 “Kojiro Saito”
2 45 “Atsushi Ueno”
これは実行時の結果ですので、これを読まれている時点ではまた違う結果になっていると思います。
あとは Twitter への投稿文を構成して、後は呟くだけ!改行は newline が使えますので、こんな感じで文章を作ってみます。
status = “MATLAB の Q&A サイト:MATLAB Answers” + newline;
status = status + “日本語質問に回答する Top アカウント (weekly)” + newline + newline;
for ii=1:min(height(dataset),5)
status = status + “- ” + dataset.nickname(ii) + “さん” + newline;
end
status = status + newline + “ありがとうございます!” + newline;
status = status + “詳細:” + baseURL;
disp(status);
MATLAB の Q&A サイト:MATLAB Answers
日本語質問に回答する Top アカウント (weekly)
– Kojiro Saitoさん
– Atsushi Uenoさんありがとうございます!
詳細:https://jp.mathworks.com/matlabcentral/answers/contributors/?filter=week
できあがり。

4. Twitter で呟く

Twitter に投稿するには Twitter API の取得が必要でその審査がちょっとハードル高い・・と心配された方。ご安心ください。ThingSpeak では ThingTweet という機能を提供していて、Twitter アカウントとリンクすれば、ThingSpeak 経由で Tweet することができます。Twitterアカウントをリンクして API Key を取得します。
もちろんできることは文字列を呟くだけ・・なので Twitter API と比較するとかなり機能は限定されますが、今回の用途には十分です。
コードはこんな感じ。
tturl=‘https://api.thingspeak.com/apps/thingtweet/1/statuses/update’;
api_key = getenv(‘THINGTWEETAPIKEY’); % 隠しておきます(適宜変更してください)
options = weboptions(‘MediaType’,‘application/x-www-form-urlencoded’);
options.Timeout = 10;
webwrite(tturl, ‘api_key’, api_key, ‘status’, status, options);
ThingSpeak を使った Twitter Bot の作り方については Qiita の MATLAB Answers の新着質問をお知らせする Twitter bot (Powered by ThingSpeak) も参考にしてください。

5. GitHub Actions で定期実行

さて、以上の処理(コード全体は tweetRanking_JP.m を見てください)を定期実行させるのに、今回は GitHub Action を使ってみます。ThingSpeak 上で MATLAB コードを実行できますし、TimeControl 機能があるので一定時間毎に実行させる設定は可能です。
ただ、ここはコードも GitHub に公開していることですし、せっかくなので(?)GitHub Action を使ってみます。MATLAB Actions が用意されているので MATLAB ライセンスは不要です。API_Key も Secrets 機能で隠ぺい化できますし、コードも公開できるメリットは大きいですね。
GitHub Action の設定はレポジトリ内の .github/workflows に yml ファイルを設定するだけ。
name: Run MATLAB Script on GitHub-Hosted Runner
on:
schedule:
– cron: ‘0 23 * * 0’
jobs:
my-job:
name: Run MATLAB Script
runs-on: ubuntu-latest
steps:
– name: Check out repository
uses: actions/checkout@v2
– name: Set up MATLAB
uses: matlab-actions/setup-matlab@v1
– name: Run script
uses: matlab-actions/run-command@v1
env:
THINGTWEETAPIKEY: ${{ secrets.THINGTWEETAPIKEY }}
with:
command: tweetRanking_JP
こんな感じです。cron: ‘0 23 * * 0’ のおまじないは UTC 23:00(日曜日)に実行してねという設定です。これは日本時間(JST)だと月曜日の朝 8 時ですね。
ポイントとしては API Key は実行時に環境変数として設定することで、MATLAB コードからも参照できるようになっています。

まとめ

毎週月曜日の朝8時に、ここで紹介したコードが実行され @MATLABAnswers から感謝の Tweet ができるようになりました。MATLAB Answers に回答くださっている皆様、本当にありがとうございます。
また、GitHub Actions は MATLAB のライセンス不要で使える=ややこしい設定不要なのでかなりお手軽ですので遊んでみてください。こんなことに使っているよ!という方、どんな GitHub x MATLAB 芸を構築されているのか、ぜひ教えてください。
|
  • print
  • send email

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.