2017年12月04日(月)

PubMedの新着論文RSSをSlackに流す

投稿者:

皆さん、日々山のように出版され続ける新しい論文をどうやってチェックしていますか? PubMedにはRSSフィードの機能があるので、ある条件で検索した結果を自動的に配信させることができるのですが、一番知りたい情報である「タイトル」「著者」「雑誌名」の3つをいい感じで一覧表示できるRSSリーダーが見つかりません(昔はSafariに付いていたRSSリーダーやGoogle謹製のRSSリーダーが結構良かったのですが、いつの間にかそれらは無くなってしまいました)。そこで、みんな大好きSlackにPubMedのRSSフィードを自動的に流すことにしてみました。

I. Slackの準備

まだ研究室でSlackを導入していない場合は、まずはぜひ一度試してみることをおすすめします。メールを送るよりも敷居が低く気軽にやりとりできますし、無料プランでも十分実用的に使えます。気に入って有料プランに申し込む場合でも、大学の研究室の場合は85%引きという太っ腹なディスカウントが受けられます。

実はもともとSlackにもRSSリーダーの機能は備わっているのですが、なぜかPubMedのRSSとは相性が悪いらしく、少なくとも私が試した限り、いくら待っても新着論文が配信されませんでした。そこで、SlackでPubMedのRSSを受け取るしかけを別途用意することにしました。

Slackで外部からメッセージを受け取るには、あらかじめ設定が必要になります。いくつか方法がありますが、ここではAPIトークンを使うという少し古い(あまりセキュアではないけれども便利な)方法をご紹介します。もし、特定のチャンネル(あるいは特定の個人の@slackbot)だけでRSSが受け取れれば良いのであれば、Incoming Webhooksを使った方が楽ですし、今時はSlackアプリを作成するのが推奨されている様ですが、とりあえず以下の様に設定してみてください。

  1. ブラウザでSlackにログインする。(または、Slackアプリの「Manage apps」を押してブラウザを開く。)
  2. ログインした状態で https://api.slack.com/custom-integrations/legacy-tokens にアクセスする。
  3. 画面中程にある「Create token」を押す。
  4. xoxp-12345678901-12345678901-12345678901-1234567890 というような文字列のトークンが作られるので、それを丸ごとコピーして、どこかにメモしておく。(このAPI Tokenがあれば、Slackの中で「何でもやりたい放題できてしまう」ので、くれぐれも取り扱いには注意してください。)


II. PubMedでRSSフィードを設定する

以下の手順で、PubMedから自分の好きな論文に関するRSSフィードのURLを取得してください。

  1. https://www.ncbi.nlm.nih.gov/pubmed/ から通常通り検索する。([AU] [TI]などのタグやAND/ORも使いながら、自分のチェックしたい論文をうまく絞り込んでください。Advanced Searchを使ってもかまいません。)
  2. 検索窓のすぐ下にある「Create RSS」をクリック。
  3. ポップアップが出てくるので、一番下の「Create RSS」ボタンを押す。(通常の場合、Number of items displayedはデフォルトの15のままで良いです。この数字はあまり増やさない方が良いと思います。)
  4. さらにポップアップが出てくるので「XML」ボタンを押す。
  5. 別窓でXMLが開くので、ブラウザのアドレスバーにあるURL(https://eutils.ncbi.nlm.nih.gov/entrez/eutils/erss.cgi?rss_guid=...... というもの)を丸ごとコピーして、どこかにメモしておく。(もし、メールソフト等が開いてしまう場合は、「XML」ボタンを右クリックして、「リンクのアドレスをコピー」を行って下さい。)
  6. 必要に応じて別の検索条件で1~5を繰り返し、それぞれRSSフィードのURLを取得してメモしておく。

III. 専用のGoogleスプレッドシートを作る

今回は、Googleスプレッドシート上にRSSフィードの情報を羅列し、決まった時間にそれらを一括してチェックさせ、新しい論文があればSlackに流す、というしくみを作ります。大学の研究室では無料のG Suite for Educationを使うのがおすすめですが、個人のGoogleアカウントを使ってもかまいません。

  1. Googleスプレッドシートの右下の赤い+を押し、新しいスプレッドシートを作成する。「無題のスプレッドシート」という名前は適宜変更する。
  2. B列には、手順II.で取得したRSSフィードのURLを順番に縦に貼り付ける。
  3. A列には、それぞれのRSSフィードに分かりやすい名前を付けたものを記入する。(必ずしも最初のPubMedでの検索キーワードと同じにする必要はありません。)
  4. C列には、新着論文一覧の配信先を記入する。皆で論文を共有したい場合はSlackのチャンネル名(#から始まる)を、個人個人で(マニアックな?)論文をチェックしたい場合は個人の表示名(@から始まる)を書く。

こんな感じになります。


IV. Google Apps Scriptを仕込む

ここで、自動化の要であるGoogle Apps Scriptの設定を行います。自前のサーバが無くても、お手軽に色々なことが自動化でき、Slackとの相性も良いので重宝しています。

  1. 手順III.で作ったスプレッドシートの「ツール」メニューの中の「スクリプトエディタ...」をクリック。
  2. 別ウィンドウでスクリプトエディタが開く。「無題のプロジェクト」というプロジェクト名は適宜変更する。
  3. 「リソース」メニューの中の「ライブラリ...」をクリック。(プロジェクト名を変更していない場合は、ここで改めて新しい名前を付けるように言われます。)
  4. 「ライブラリを追加」のところに M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO という文字列をそのままコピペして「追加」を押す。(これにより、「Slack BotをGASでいい感じで書くためのライブラリ」が使用可能になり、Google Apps ScriptからSlackを簡単に操作できるようになります。素晴らしい。)
  5. 「バージョン」は一番大きい番号(22)を選んで「保存」を押す。
  6. スクリプトエディタの中に出ている 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エラーを出すことがあるのでtryで回避
    } catch (e) {
      continue; // もしエラーが出てもとりあえず無視(次回fetchできれば良しとする)
    }

    // Parse
    var rss = XmlService.parse(rssText);
    var items = rss.getRootElement().getChildren('channel')[0].getChildren('item');

    // Check new items
    var news = [];
    for each(var item in items) {
      if (lastFetched.indexOf(item.getChild('guid').getText()) < 0) {
        news.push(item);
      }
    }

    if (news.length > 0) {
      // Prepare attachments
      var att = [];
      for each(var item in news) {
        var title = item.getChild('title').getText();
        var authors = item.getChild('author').getText().replace(/^\s+/, ''); // なぜか先頭にあるスペースを削除
        var journal = item.getChild('category').getText();
        var link = item.getChild('link').getText();
        var paperInfo = authors + '\n' + '_*' + journal + '*_';

        att.push({
          title: title,
          title_link: link,
          color: '#336699', // NCBIカラー(自由に変更してください)
          text: paperInfo,
          mrkdwn_in: ['text'],
        })
      }

      // Post Slack
      var app = SlackApp.create(TOKEN);
      var message = 'Here are new papers for *"' + keyword + '"* :eyes:'; // 配信の際のメッセージ(自由に変更してください)
      app.postMessage(channel, message, {
        username: 'PubMed RSS', // RSSを配信してくれるボットの名前(自由に変更してください)
        icon_emoji: ':rolled_up_newspaper:', //RSSを配信してくれるボットのアイコン(自由に変更してください)
        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(','));
  }
}
  1. 2行目の var TOKEN = のあとを、手順I.で記録しておいたSlackのAPIトークンに書き換える。必ずクオーテーションマークで囲ってください。
  2. (オプション) RSSを配信してくれるボットの名前やアイコン、配信の際のメッセージ、記事一覧表示の縦棒(Attachment)の色などは自由に変更してください。
  3. フロッピーディスク(懐かしい!)マークの「保存」を押す。
  4. 「関数を選択」のところで「PubMedSlack」を選び、「▶ (実行)」を押す。
  5. しばらく待つと「承認が必要です」と出るので、「許可を確認」を押す。
  6. 自分のアカウントを選択し、下にスクロールして「許可」を押す。
  7. 上部に「関数 PubMedSlack を実行中...」のメッセージが出るので、消えるまでしばらく待つ。
  8. うまく行っていれば、この段階で、C列で設定したSlackのチャンネルに(または@slackbotから個人宛てのDirect Messageとして)、新着論文一覧が届くはずです。こんな感じ。(うちの研究室では、貝のアイコンの「あるご」という名前のボットが活躍しています。)

このように「タイトル」「著者」「雑誌名」がきれいに並び、タイトルをクリックすれば、PubMedの当該論文のページに飛べます。スマホのSlackアプリからも見やすいです。

なお、このときスプレッドシートのD列を見に行くと、「PubMed:12345678,PubMed:23456789...」と言うような、最新論文のPubMed IDの一覧が記入されているはずです。これは、次にRSSフィードを受け取る際、どれが新しい論文かをチェックするための記録ですので、とりあえず無視しておいて下さい。

もしエラーが出た場合やSlackに配信されない場合は、どこかがおかしいと思われるので、上記の手順を確認してみてください。特に、スクリプト中のAPIトークンの部分は必ず手順I.で取得したものに書き換えてください。


V. スクリプトのトリガー(タイマー)を設定する

ここまで来たらあと少し。定期的にスクリプトを実行するためのトリガーを設定します。

  1. スクリプトエディタの「編集」メニューの中の「現在のプロジェクトのトリガー」を選ぶ。
  2. 「トリガーが設定されていません。今すぐ追加するにはここをクリックしてください。」をクリック。
  3. 「実行」に「PubMedSlack」が表示されていることを確認し、「時間主導型」を選ぶ。
  4. 「日タイマー」「午前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の一例でした。では、効率的な研究室ライフを!


謝辞

以下の情報を大いに参考にさせて頂きました。ありがとうございます!


追記

「ゲノムのほうの愛ちゃん」こと理研の二階堂さんから、IFTTTを使うと、PubMedのRSSをお手軽にSlackに流せるとの情報を頂きました。二階堂さんありがとうございます。

例えば以下のように設定すると、「タイトル」と「著者」をいい感じで一覧して見ることができます。タイトルからPubMedの当該論文のページに飛べます。

  • Message: {{EntryAuthor}}
  • Title (optional): {{EntryTitle}}
  • Title URL (optional): {{EntryUrl}}
  • Thumbnail URL (optional): 空欄

なお、IFTTTでは「雑誌名」だけを抜き出すことは出来ない様ですが、タイトル・著者・アブストラクト・PubMed IDなどもすべて含めた形であれば、

  • Message: {{EntryContent}}

と設定することによって、雑誌名も表示させることが可能です。文字数は多くなりますが、アブストラクトまで読めてしまうので、一度に流れてくる論文数が少ない場合は便利かも知れません。

(私自身は使ったことが無いのですが) ZapierIntegromat (正規表現が使えるらしいので自由度は高そう)などの選択肢もありますし、お好みでぜひ色々な方法をお試し下さい。

泊 幸秀

東京大学 分子細胞生物学研究所 教授
▶ プロフィールはこちら

コメントする

コメントはどなたでも歓迎します。メンバーの方はログインしてからコメントして下さい。

ブログアーカイブ

ログイン

サイト内検索