I. Slackの準備
まだ研究室でSlackを導入していない場合は、まずはぜひ一度試してみることをおすすめします。メールを送るよりも敷居が低く気軽にやりとりできますし、無料プランでも十分実用的に使えます。気に入って有料プランに申し込む場合でも、大学の研究室の場合は85%引きという太っ腹なディスカウントが受けられます。
実はもともとSlackにもRSSリーダーの機能は備わっているのですが、なぜかPubMedのRSSとは相性が悪いらしく、少なくとも私が試した限り、いくら待っても新着論文が配信されませんでした。そこで、SlackでPubMedのRSSを受け取るしかけを別途用意することにしました。
Slackで外部からメッセージを受け取るには、あらかじめ設定が必要になります。いくつか方法がありますが、ここではAPIトークンを使うという少し古い(あまりセキュアではないけれども便利な)方法をご紹介します。もし、特定のチャンネル(あるいは特定の個人の@slackbot)だけでRSSが受け取れれば良いのであれば、Incoming Webhooksを使った方が楽ですし、今時はSlackアプリを作成するのが推奨されている様ですが、とりあえず以下の様に設定してみてください。
- ブラウザでSlackにログインする。(または、Slackアプリの「Manage apps」を押してブラウザを開く。)
- ログインした状態で https://api.slack.com/custom-integrations/legacy-tokens にアクセスする。
- 画面中程にある「Create token」を押す。
-
xoxp-12345678901-12345678901-12345678901-1234567890
というような文字列のトークンが作られるので、それを丸ごとコピーして、どこかにメモしておく。(このAPI Tokenがあれば、Slackの中で「何でもやりたい放題できてしまう」ので、くれぐれも取り扱いには注意してください。)
II. PubMedでRSSフィードを設定する
以下の手順で、PubMedから自分の好きな論文に関するRSSフィードのURLを取得してください。
- https://pubmed.ncbi.nlm.nih.gov/ から通常通り検索する。([AU] [TI]などのタグやAND/ORも使いながら、自分のチェックしたい論文をうまく絞り込んでください。Advanced Searchを使ってもかまいません。)
- 検索窓のすぐ下にある「Create RSS」をクリック。
- 下に現れる「Create RSS」という青いボタンを押す。(通常の場合、Number of items displayedはデフォルトの15のままで良いです。この数字はあまり増やさない方が良いと思います。)
- 「Copy」ボタンを押すし、クリップボードにコピーされたRSSのURL (https://pubmed.ncbi.nlm.nih.gov/rss/search/... というもの)を丸ごとコピーして、どこかにメモしておく。
- 必要に応じて別の検索条件で1~4を繰り返し、それぞれRSSフィードのURLを取得してメモしておく。
III. 専用のGoogleスプレッドシートを作る
今回は、Googleスプレッドシート上にRSSフィードの情報を羅列し、決まった時間にそれらを一括してチェックさせ、新しい論文があればSlackに流す、というしくみを作ります。大学の研究室では無料のG Suite for Educationを使うのがおすすめですが、個人のGoogleアカウントを使ってもかまいません。
- Googleスプレッドシートの右下の赤い+を押し、新しいスプレッドシートを作成する。「無題のスプレッドシート」という名前は適宜変更する。
- B列には、手順II.で取得したRSSフィードのURLを順番に縦に貼り付ける。
- A列には、それぞれのRSSフィードに分かりやすい名前を付けたものを記入する。(必ずしも最初のPubMedでの検索キーワードと同じにする必要はありません。)
- C列には、新着論文一覧の配信先を記入する。皆で論文を共有したい場合はSlackのチャンネル名(#から始まる)を、個人個人で(マニアックな?)論文をチェックしたい場合は個人の表示名(@から始まる)を書く。
こんな感じになります。
IV. Google Apps Scriptを仕込む
ここで、自動化の要であるGoogle Apps Scriptの設定を行います。自前のサーバが無くても、お手軽に色々なことが自動化でき、Slackとの相性も良いので重宝しています。
- 手順III.で作ったスプレッドシートの「ツール」メニューの中の「スクリプトエディタ...」をクリック。
- 別ウィンドウでスクリプトエディタが開く。
- 「新しい App Script エディタをお試し下さい」と表示されている場合は、そのまま「閉じる」(あるいは「次回から表示しない」)。新しいエディタが表示されている場合は、右上にある「以前のエディタを使用」をクリック(アンケートなどが表示されるが、無視して閉じる)。
- 「実行」メニューの中の「Chrome V8 を搭載した新しい Apps Script ランタイムを無効にする」をクリックする。
- 左上の「無題のプロジェクト」というプロジェクト名をクリックし、適宜変更する。
- 「リソース」メニューの中の「ライブラリ...」をクリック。(プロジェクト名を変更していない場合は、ここで改めて新しい名前を付けるように言われます。)
-
「ライブラリを追加」のところに
M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO
という文字列をそのままコピペして「追加」を押す。(これにより、「Slack BotをGASでいい感じで書くためのライブラリ」が使用可能になり、Google Apps ScriptからSlackを簡単に操作できるようになります。素晴らしい。) - 「バージョン」は一番大きい番号(22)を選んで「保存」を押す。
-
スクリプトエディタの中に出ている
function myFunction() {}
は一旦削除し、まっさらになったところに、以下のスクリプトを貼り付ける。(「RSS Mailer by Google Apps Script」の記事を参考にし、コードの一部を使わせて頂きました。)
function PubMedSlack() {
var TOKEN = 'xoxp-12345678901-12345678901-12345678901-1234567890'; // 手順I.でメモをしたAPI Tokenに必ず書き換えてください。
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var data = sheet.getRange(1, 1, sheet.getLastRow(), 4).getValues();
for (var i = 0; i < data.length; i++) {
var keyword = data[i][0];
var feedURL = data[i][1];
var channel = data[i][2];
var lastFetched = data[i][3];
// Fetch
try {
var rssText = UrlFetchApp.fetch(feedURL).getContentText(); // たまにPubMedが404を出すことがある
} catch (e) {
continue; // もしエラーが出てもとりあえず無視(次回fetchできれば良しとする)
}
// Parse
var rss = XmlService.parse(rssText);
var items = rss.getRootElement().getChildren('channel')[0].getChildren('item');
var nsDc = XmlService.getNamespace("dc", "http://purl.org/dc/elements/1.1/");
// Check new items
var news = [];
for each(var item in items) {
if (lastFetched.indexOf(item.getChildText("guid")) < 0) {
news.push(item);
}
}
if (news.length > 0) {
// Prepare attachments
var att = [];
for each(var item in news) {
var title = item.getChildText("title").replace(/<\/?em>/g,"");
var journal = item.getChildText("source", nsDc);
var authors = item.getChildren("creator", nsDc);
var authorList = [];
for (var j = 0; j < authors.length; j++) {
authorList.push(authors[j].getText());
}
var link = item.getChild("link").getText();
var message = authorList.join(", ") + '\n' + '_*' + journal + '*_';
att.push({
title: title,
title_link: link,
color: "#336699", //論文一覧に表示される縦線の色 (自由に変更して下さい)
text: message,
mrkdwn_in: ["text"],
})
}
// Post Slack
var app = SlackApp.create(token);
app.postMessage(channel, 'Here are new papers for *"' + keyword + '"* :eyes:', {
username: "あるご", //お知らせしてくれるボットの名前 (自由に変更して下さい)
icon_emoji: ":shell:", //ボットの絵文字 (自由に変更して下さい)
attachments: JSON.stringify(att),
});
}
// Record fetched items
var guids = [];
for each(var item in items) {
guids.push(item.getChild("guid").getText());
}
sheet.getRange(i + 1, 4).setValue(guids.join(','));
}
}
-
2行目の
var TOKEN =
のあとを、手順I.で記録しておいたSlackのAPIトークンに書き換える。必ずクオーテーションマークで囲ってください。 - (オプション) RSSを配信してくれるボットの名前やアイコン、配信の際のメッセージ、論文一覧表示の縦線(Attachment)の色などは自由に変更してください。
- フロッピーディスク(懐かしい!)マークの「保存」を押す。
- 「関数を選択」のところで「PubMedSlack」を選び、「▶ (実行)」を押す。
- しばらく待つと「承認が必要です」と出るので、「許可を確認」を押す。
- 自分のアカウントを選択し、下にスクロールして「許可」を押す。
- 上部に「関数 PubMedSlack を実行中...」のメッセージが出るので、消えるまでしばらく待つ。
- うまく行っていれば、この段階で、C列で設定したSlackのチャンネルに(または@slackbotから個人宛てのDirect Messageとして)、新着論文一覧が届くはずです。こんな感じ。(うちの研究室では、貝のアイコンの「あるご」という名前のボットが活躍しています。)
このように「タイトル」「著者」「雑誌名」がきれいに並び、タイトルをクリックすれば、PubMedの当該論文のページに飛べます。スマホのSlackアプリからも見やすいです。
なお、このときスプレッドシートのD列を見に行くと、「PubMed:12345678,PubMed:23456789...」と言うような、最新論文のPubMed IDの一覧が記入されているはずです。これは、次にRSSフィードを受け取る際、どれが新しい論文かをチェックするための記録ですので、とりあえず無視しておいて下さい。
もしエラーが出た場合やSlackに配信されない場合は、どこかがおかしいと思われるので、上記の手順を確認してみてください。特に、スクリプト中のAPIトークンの部分は必ず手順I.で取得したものに書き換えてください。
V. スクリプトのトリガー(タイマー)を設定する
ここまで来たらあと少し。定期的にスクリプトを実行するためのトリガーを設定します。
- スクリプトエディタの「編集」メニューの中の「現在のプロジェクトのトリガー」を選ぶ。
- 「トリガーが設定されていません。今すぐ追加するにはここをクリックしてください。」をクリック。
- 「実行」に「PubMedSlack」が表示されていることを確認し、「時間主導型」を選ぶ。
- 「日タイマー」「午前9時~10時」や、「時タイマー」「4時間ごと」など、新着論文をチェックさせたいタイミングを選んで「保存」。トリガーは複数設定できるので、朝夕2回の「日タイマー」を設定するなども可能です。
お疲れ様でした。これで、設定したトリガーのタイミングでPubMedのRSSフィードがチェックされ、新着があればSlackに流れてくるはずです。便利ですね。
Slackで受け取るRSSフィードを変更したい場合は、スプレッドシートを直接編集してください。理論上は行を増やせばいくらでもRSSフィードの受信を追加できますが、あまりにも数が多くなると不具合が出る可能性があるので、ご注意ください。また、行ごと削除してしまえば該当するRSSフィードの受信は止まります。スプレッドシートから削除しても、最初にPubMedから取得したRSSフィードのURLはずっと有効なので、メモしておいたURLを再度貼り付ければ、受信を再開できます。なお、現在のスクリプトは、PubMed以外(bioRxivなど)の形式のRSSフィードには対応していません。
さらに便利に使うためには、SlackのSlash Commandを設定し、Google Apps Scriptで適切なスクリプト書いて橋渡しすれば、以下の様に、Slackから /pubmed [keyword] [feed url]
の様な感じのコマンドを入力することによって、RSSフィードの受信設定を直接コントロールする(スプレッドシートの内容をSlackから遠隔で変更させる)ことが可能になります。これはまたの機会にご紹介できればと思います(果たして需要はあるでしょうか・・・)。
以上、SlackとGoogle Apps Scriptを活用した研究室Hackの一例でした。では、効率的な研究室ライフを!
謝辞
以下の情報を大いに参考にさせて頂きました。ありがとうございます!
- Slack BotをGASでいい感じで書くためのライブラリを作った (Qiita @soundTricker)
- RSS Mailer by Google Apps Script (アスタネットブログ)
追記
こんな感じです。"single-cell RNA-seq" をPubMedで検索して、RSSのURLを得たあと、IFTTTに設定。slackに流れてきます。 pic.twitter.com/CXO2Zr39gC
— ゲノムのほうの愛ちゃん (@dritoshi) 2017年12月6日
「ゲノムのほうの愛ちゃん」こと理研の二階堂さんから、IFTTTを使うと、PubMedのRSSをお手軽にSlackに流せるとの情報を頂きました。二階堂さんありがとうございます。
例えば以下のように設定すると、「タイトル」と「著者」をいい感じで一覧して見ることができます。タイトルからPubMedの当該論文のページに飛べます。
-
Message:
{{EntryAuthor}}
-
Title (optional):
{{EntryTitle}}
-
Title URL (optional):
{{EntryUrl}}
- Thumbnail URL (optional): 空欄
なお、IFTTTでは「雑誌名」だけを抜き出すことは出来ない様ですが、タイトル・著者・アブストラクト・PubMed IDなどもすべて含めた形であれば、
-
Message:
{{EntryContent}}
と設定することによって、雑誌名も表示させることが可能です。文字数は多くなりますが、アブストラクトまで読めてしまうので、一度に流れてくる論文数が少ない場合は便利かも知れません。
(私自身は使ったことが無いのですが) ZapierやIntegromat (正規表現が使えるらしいので自由度は高そう)などの選択肢もありますし、お好みでぜひ色々な方法をお試し下さい。