Python・Webhook・IFTTTを使って、興味あるカテゴリーのarXiv新規投稿論文のお知らせをメールさせてみた

投稿日:  更新日:2022/09/02

IFTTT Python 数学 物理学

B!
Daniel AgreloによるPixabay(https://pixabay.com/)からの画像

こんにちは, Shinoryoです.

論文を読むような方は, 学術論文のアーカイブサービスであるarXivを利用される方は多いと思います.

そこで, PythonIFTTTを使用して, arXivへの新規投稿論文の情報をGoogle翻訳で日本語訳にしてメールさせてみました.

IFTTTの設定

まずは, IFTTTの設定を行います. IFTTTとは, さまざまなサービスを連携して, 「トリガーとなるあるイベントが発生した」場合(IF This), 「あるイベントを発生させる」(Then That)ことができる(合わせてIF This Then That = IFTTT)ものになります.

概要

以下の図のように, WebhookGmailをつなげます.

IFTTTの設定の概要

Webhook

Webhookとは, さまざまなウェブリクエストを作成または受信できる機能のことです. 私もあまり詳細は分かりませんが, 以下のようになるでしょうか.

  1. 何かしらのトリガーとなるイベントが発生する(データが追加される, 特定の時刻になる等?)
  2. そのイベントにより指定したURLへのHTTP通信が発生し, データが送信される

もし具体的に興味があれば, 例えば以下のWebページは参考になるかもしれません.

Webhookでは, 「Receive a web request」のトリガーを設定し, 下の図のようにEvent Nameを設定します. Event Nameは任意で構いません.

IFTTTのWebhookの設定

Gmail

Gmailでは, 「Send yourself an email」のイベントを設定し, 例えば下の図のように設定します. この後のPythonプログラムに合わせてこのようにしていますが, 「Value1, Value2, Value3に3つの値が保存され, その値をGmailのイベントの設定に使うことができる」ということが分かっていれば, 柔軟に設定を変更することができると思います.

IFTTTのGmailの設定

WebhookのURLを取得しておく

この後のPythonプログラムで用いる, WebhookのURLを取得します. まず, IFTTTのMy ServiceからWebhookを選択し, 右上の「Documentation」を選択します.

IFTTTのMy ServiceからWebhookを選択した後

そして「To Trigger an Event」の下のURLを確認します.

IFTTTのWebhookのDocumentation

このURLの真ん中の四角に, 上記のIFTTTのWebhookの設定のEvent Nameで設定した名前を入れたURLを確認してください. これを後に用います.

Python

Pythonのコード例

私は以下のようなPythonプログラムを用いています.

import arxiv
import datetime
from googletrans import Translator
import requests
import time
translator = Translator()
# パラメータの設定
# WebhookのURL
API_URL = "Webhook_URL"
# クエリの設定(カテゴリ)
QUERY_cat = "(cat:astro-ph.CO OR astro-ph.GA)"
# 情報を確認する時刻の設定
# デフォルトは一週間前
todaytime = datetime.datetime.utcnow()
endtime = todaytime - datetime.timedelta(days=7)
starttime = todaytime - datetime.timedelta(days=8)
todaytime = todaytime.strftime("%Y%m%d%H%M%S")
endtime = endtime.strftime("%Y%m%d%H%M%S")
starttime = starttime.strftime("%Y%m%d%H%M%S")
print("-------from_arXiv_to_Gmail.py-------")
print("ただいまの日時:" + todaytime)
print("出力日時:" + starttime + " TO " + endtime)
# arXivから情報を取得する(result_list)
result_list = arxiv.Search(
query = QUERY_cat + " AND submittedDate:[" + starttime + " TO " + endtime + "]",
# max_results = 1,
sort_by = arxiv.SortCriterion.SubmittedDate
)
# 情報を出力したカウント(count)
count = 1
# 「出力開始」のログを出力
print("-------出力開始-------")
size = len([result for result in result_list.get()])
# result_listでループ
for result in result_list.get():
# 細かな情報を取得
title = result.title
authors = result.authors
date = result.published
category = result.categories
journalref = result.journal_ref
abst = result.summary
comment = result.comment
absurl = result.entry_id
pdfurl = result.pdf_url
doiurl = result.doi
# タイトルの日本語訳を取得
title_jpn = translator.translate(title, src='en' ,dest='ja').text
time.sleep(1)
# 著者を整形
new_authors = []
for author in authors:
new_authors.append(author.name)
new_authors = "; ".join(new_authors)
# ジャーナル情報を整形
if journalref == None:
journalref = "No Journal Reference."
# カテゴリーを整形
new_category = ", ".join(category)
# 概要の日本語訳を取得
abst = abst.replace("\n"," ")
abst_jpn = translator.translate(abst, src='en' ,dest='ja').text
time.sleep(1)
# コメントの日本語訳を取得
if comment == None:
comment = "No comment."
comment_jpn = translator.translate(comment, src='en' ,dest='ja').text
time.sleep(1)
# doiurlを整形
if doiurl == None:
doiurl = "No doi link."
else:
doiurl = "https://doi.org/" + doiurl
# ログを出力
print()
print("-------" + str(count) + "/" + str(size) +"ページ目-------")
print("Title: {}".format(title))
print("タイトル: {}".format(title_jpn))
try:
print("Authors: {}".format(new_authors))
except Exception as e:
print("Authors: " + str(e))
print("Published(UTC): " + str(date))
print("Journal Reference: " + journalref)
print("Categories: " + new_category)
print("")
print("Abstract: ")
try:
print("{}".format(abst))
except Exception as e:
print("{}".format(e))
print("")
print("概要: ")
try:
print("{}".format(abst_jpn))
except Exception as e:
print("{}".format(e))
print("")
print("Comment: ")
try:
print("{}".format(comment))
except Exception as e:
print("{}".format(e))
print("")
print("コメント: ")
try:
print("{}".format(comment_jpn))
except Exception as e:
print("{}".format(e))
print("")
print("URL: {}".format(absurl))
print("PDFのURL: {}".format(pdfurl))
print("doiのURL: {}".format(doiurl))
# WebhookへPost
if doiurl == "No doi link.":
message = "\n".join(["Title: " + title + "<br>タイトル: " + title_jpn + "<br>Authors: " + new_authors + "<br>Published(UTC): " + str(date) + "<br>Journal Reference: " + journalref + "<br>Categories: " + new_category + "<br><br>Abstract: <br>" + abst + "<br><br>概要: <br>" + abst_jpn + "<br><br>Comment: <br>" + comment + "<br><br>コメント: <br>" + comment_jpn + "<br><br>URL: <a href=\"" + absurl + "\">" + absurl + "</a>" + "<br>PDFのURL: <a href=\"" + pdfurl + "\">" + pdfurl + "</a>" + "<br>doiのURL: " + doiurl])
else:
message = "\n".join(["Title: " + title + "<br>タイトル: " + title_jpn + "<br>Authors: " + new_authors + "<br>Published(UTC): " + str(date) + "<br>Journal Reference: " + journalref + "<br>Categories: " + new_category + "<br><br>Abstract: <br>" + abst + "<br><br>概要: <br>" + abst_jpn + "<br><br>Comment: <br>" + comment + "<br><br>コメント: <br>" + comment_jpn + "<br><br>URL: <a href=\"" + absurl + "\">" + absurl + "</a>" + "<br>PDFのURL: <a href=\"" + pdfurl + "\">" + pdfurl + "</a>" + "<br>doiのURL: <a href=\"" + doiurl + "\">" + doiurl + "</a>"])
title = "arXiv投稿通知(" + str(count) + "/" + str(size) + "): " + title
response = requests.post(API_URL, data={"value1": message, "value2": title, "value3": pdfurl})
# countを+1
count += 1
# 5秒間休止
time.sleep(5)
# 「出力完了」のログを出力
print()
print("-------出力完了-------")
  • arxivモジュールが更新されたようなので, それに対応させました.
    • arxiv.Searchで, arXivから情報を検索してくるようになりました.
    • result.authorsで著者名を取得すると, 「arxiv.Result.Author("AAA")」のようなもののリストが取得されます. そのため, 「著者を整形」のコメントより下のような処理を施すことで, 著者名が「; 」でつながった文字列を得ています.
  • googletransモジュールは, 最新ver.を入手した方がバグが少なくなるようです. 一応「time.sleep(1)」も入れていますが, ご参考までに.
    $ pip install googletrans==4.0.0-rc1

まとめ

あとはこれを毎朝実行する等の状況があれば強いです. 現状, 私はそれを実行する設定ができていないので, batファイルを作成してせめて1ダブルクリックで実行できるようにはしています. 毎朝実行するように設定出来たら, また新記事で紹介するかもしれません!

参考にしたサイト等