こんにちは。takapy(@takapy0210)です。
最近下記のような勉強会が賑わっており、論文を読む機運が高まってきているのでは?と思い始めています。
しかし、そもそも自分の読みたい内容の論文を探すのが難しかったり、時間がかかったりして、どうしてもはじめの一歩の障壁が高いよな〜などと感じていました。
そこで、無料かつタイムリーに、しかもなるべく労力をかけずにいい感じの論文が知りたいぞ〜というお気持ちになり、AWS Lambdaを使用してarXivから論文を取得して(必要であれば日本語翻訳して)slackに通知するようなコトをやってみました。
arXivとは
以下、wiki引用
arXivは、物理学、数学、計算機科学、量的生物学、計量ファイナンス、統計学の、プレプリントを含む様々な論文が保存・公開されているウェブサイトである。論文のアップロード、ダウンロードともに無料で、論文はPDF形式である。1991年にスタートして、プレプリント・サーバーの先駆けとなったウェブサイトである。
世界中の強い人たちが書いた論文が載っているサイトです。
結果
こんな感じで、毎朝10時に前日更新された論文が少しリッチに(日本語翻訳され)slack通知されます。
slackの設定
slackにIncoming Webhooksアプリケーションを追加し、そこからWEBHOOK_URLを取得します。
(このURLは後半で使用します)
詳しくは下記を参照してみてください。 qiita.com
AWSの設定
AWSのアカウントを所持している前提で進めます。
アカウント登録や初期設定については下記を参照してみてください。
AWS Lambda
AWS Lambdaのコンソールにアクセスし、関数の作成をクリックします。
基本的な情報を入力し、関数を作成します。
関数名には任意の値を設定していただいて構いませんが、ランタイムはPython 3.7を選択してください。
すると、下記のように初期関数が生成されます。
この関数は後述の作業で上書きしますので、ここでコンソールからは一旦離れます。
googletrans(google翻訳)パッケージの追加
今回のLambda関数では、googletransを利用します。しかしデフォルトではLambdaにgoogletransがインストールされていないので、No module named 'googletrans'
というエラーが発生してしまいます。
このエラーを解決するために、今回はpipを使用してgoogletransをローカルディレクトリにインストール→デプロイパッケージの作成、そしてそれをLambdaへ追加していきます。
このときにLambda関数の実行スクリプトであるlambda_function.py
も一緒に作成して追加していきます。
1. 任意の場所にディレクトリを生成
$ mkdir package $ ls package
2. -t
オプションでライブラリをパッケージディレクトリにインストール
$ cd package $ pip install googletrans -t .
3. lambda_function.pyの作成
package配下に、下記のようなpythonスクリプトファイルを作成します。
ファイル名は「lambda_function.py」としてください。
import os import re import json import urllib.request import datetime from googletrans import Translator def parse(data, tag): pattern = "<" + tag + ">([\s\S]*?)<\/" + tag + ">" if all: obj = re.findall(pattern, data) return obj def get_thesis(query, basedate, previousdate, translate=True): translator = Translator() url = 'http://export.arxiv.org/api/query?search_query=submittedDate:[' + \ previousdate.strftime('%Y%m%d') + '0000+TO+' + \ basedate.strftime('%Y%m%d')+'0000]+AND+' + query data = urllib.request.urlopen(url).read().decode('utf-8') entries = parse(data, "entry") if len(entries) == 0: print('直近の論文はありません') return else: print('{}件の論文があります'.format(len(entries))) for entry in entries: # 各値の取得 url = parse(entry, "id")[0] title = parse(entry, "title")[0] title = title.replace('\n', '') title_jp = translator.translate(str(title), dest='ja').text date = parse(entry, "published")[0] date = date[:10] author = ', '.join(parse(entry, "name") ) summary = parse(entry, "summary")[0] summary = summary.replace('\n', '') # 日本語化 if translate: summary = translator.translate(str(summary), dest='ja').text attachment = { 'title': title_jp + " ( " + title + " )", 'title_link': url, "author_name": author, "fields": [ { "title": "Abstract", "value": summary }, { "title": "Published", "value": date } ] } data = { 'username': 'arXiv', 'icon_emoji': ':arxiv:', 'channel': '#python', 'attachments': [attachment] } data = json.dumps(data).encode('utf-8') # slack通知 api_url = os.environ.get('SLACK_INCOMING_WEBHOOK_URL') req = urllib.request.Request(api_url, data=data) urllib.request.urlopen(req) def lambda_handler(event, context): query = "(cat:cs.AI+OR+" + "cat:cs.CV+OR+" + "cat:cs.CL+OR+" + "cat:stat.ML) +AND+"+ \ "((abs:NLP)+OR+(abs:depth)+OR+(abs:deep)+OR+(abs:network)+OR+(abs:natural)+OR+(abs:language))" # 日本時間に合わせる basedate = datetime.datetime.now() + datetime.timedelta(hours=9) previousdate = basedate + datetime.timedelta(days=-1) get_thesis(query, basedate, previousdate, True)
補足
get_thesis関数
の引数のtranslateをFalseに設定すると、翻訳せずにslack通知させることができます。data =
の部分に記載されている情報は、皆さんのslackの設定に合わせて修正して使用してくださいquery =
の部分で検索する論文の種類を指定しています。
APIの詳細は下記に載っていますので、自分の目的に合わせて修正してみてください。 arxiv.org
4. zip化
ここまでで作成したpackageフォルダをzipに圧縮します。
$ zip -r9 ../function.zip .
上記を実行するとpackage
ディレクトリと同じ階層にfunction.zip
というファイルが出来ていると思います。
5. Lambda関数へ追加
AWS Lambdaのコンソールに戻り、.zipファイルをアップロード
を選択します。
ここで、先に作成したfunction.zip
を指定します。
すると、下記のようなモジュール群と実行ファイルがLambda上にアップロードされます。
6. タイムアウト時間の変更
デフォルトのタイムアウト時間は3秒になっているため、取得する論文の本数が多い場合はタイムアウトエラーになってしまう可能性があります。
そこで、今回は1分に変更しました。
7. 環境変数の追加
最後に、冒頭の「slackの設定」で取得したWEBHOOK_URLを環境変数に設定します。
AWS CloudWatch Events
次にlambdaの起動元となるトリガーをCloudWatch Eventsで作成します。
トリガーは毎朝10時に設定しました。
(ここでの時間はUTCなので、AM10時 - 9時間 = 1時 を設定しています)
cron式の詳細は下記を参照してください。
これにて設定終了です!
最後に
slack通知ドリブンな論文ライフをお楽しみください!