[追記]
何か質問、修正、提案があれば気軽にコメントしてください。
どんどんいいものを作って行きたいので、是非お願いします…!
[追記終わり]
毎日arxivをチェックしようと意気込んでいるのですが、なんだかんだ忘れてしまうことが多いのでいっそのこと毎日Slackにでも更新情報を流してくれるbotでも作っちゃえということで作成しました。
#こんな人におすすめ
・スクレイピングやってみたい人(seleniumとか)
・pythonでbot作ってみたい人
・arxivをチェックするの忘れる人
・arxivから興味のある論文だけを教えて欲しい人(今回やりませんが、正規表現などで簡単にできると思います。)
#こんな感じ
arxivの新規論文を毎日9時にSlackに通知してくれます。
僕の場合、日本語訳がある方がぱっと見で分かりやすいのでGoogle翻訳による日本語訳も一緒に出してます←
#インストールとセッティング
・python3系
・slackアカウント
・google chrome
ここらへんは既に使われてることが多いと思います。
##seleniumのインストール
今回自動でwebページを巡回するために利用するツールです。
pythonのパッケージとしてサポートされてるのでpipでインストールします。
pip install selenium
##chromedriverのインストール
SeleniumがChromeを操作するためのドライバーです。
macならhomebrew、linuxならlinuxbrewでインストールできます。
他OSでもここからダウンロードできます。
brew install chromedriver
##slack webhookの設定
slackに外部から投稿するためのAPIとしてWebHooksを利用します。
SlackのIncoming Webhooksを使い倒す にWebHooksの取得の仕方が記載されてるので、「Incoming Webhooksのエンドポイントを取得する」の項を順に行って設定してください。
ここで、記事にあるようにWebhookURLをメモしておいてください。 ...(1)
#Pythonコーディング
実際のコードとその説明を載せます。
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
seleniumをインポート
options = Options()
# ヘッドレスモードで起動。
options.add_argument('--headless')
# ChromeのWebDriverオブジェクトを作成する。
# Cronで動かす際には特にexecutable_pathが必要
driver = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver", chrome_options=options)
seleniumでgoogle chromeを起動。
毎回ブラウザが開くと閉じるのがめんどくさいのでheadlessモードで起動します。
executable_pathには
which chromedriver
の結果を書いてください。僕の場合は/usr/local/bin/chromedriverでした。
import slackweb
# webhookのURL
WEBHOOK_URL = "https://hooks.slack.com/services/*******/*******/***************"
# webhookをセット
slack = slackweb.Slack(url=WEBHOOK_URL)
(1)で確認したWebhookのURLを入れて(WEBHOOK_URL="ここに入れる")、slackwebにセットします。
slackwebがない場合は
pip install slackweb
でインストール。
rss = feedparser.parse("http://export.arxiv.org/rss/cs.CL")
arxivの更新情報は毎日RSSという形式で更新されていきます。
arxivの公式ページから詳細が見れます。
例えばComputer ScienceのComputation and Languageの論文の情報が知りたいときには
http://export.arxiv.org/rss/cs.CL
を見ればいいことになります。
興味のある分野に合わせてparse("ここ")を変えてください。
ここからがスクレイピングのコードです。
#英語のタイトルを日本語に翻訳する関数。
def translate(summary):
#Google翻訳を開く
sleep(3)
driver.get("https://translate.google.com/?hl=ja")
#英語を打ち込む
driver.find_element_by_id("source").send_keys(summary)
#"翻訳"ボタンを押す
driver.find_element_by_id("gt-submit").click()
#翻訳待ち
sleep(3)
#翻訳後の日本語取得
result = driver.find_element_by_id("result_box").text
return result
#論文ごとのクラス
class Entry():
def __init__(self,entry):
#著者、URL、タイトル、要約を取得。
self.author = [re.sub("<.+?>","",a) for a in entry.author.split(", ")]
self.url = entry.id
self.title = re.sub(" \(arXiv:.+\)$","",entry.title)
self.author_info = {}
#タイトルと要約を英日翻訳
def translate(self):
#translate by google translation
self.title_ja = translate(self.title)
self.summary_ja = translate(self.summary)
#RSSのエントリー(新規論文)ごとに翻訳
for one_entry in rss.entries:
try:
# Entryのクラスを作成
entry = Entry(one_entry)
# 翻訳
entry.translate()
新規論文の情報はrss.entriesにリスト形式で格納されてます。
なのでこれをfor文で回せば1論文ごとの情報が取得できます。
今回はクラスを使用して、initで著者、URL、タイトル、要約を取得しておきます(もちろんクラス使わなくてもOK)。
次に翻訳ですが、上のtranslate関数で可能です。
翻訳の際のseleniumの動きがどうなってるか気になったら、headlessモード以外で起動してやってみてください。
seleniumの使いかたは調べたら出てくると思いますが、開発は基本的に
- ページのソースをみる(chromeの場合、知りたい要素を右クリックして"検証")
2. 要素のidかxpathを調べてseleniumで指定
3. click()クリック/ textで本文取得/ etc...
の流れです。
#論文ごとのクラス
class Entry():
##initとtranslate関数がここにあります##
def arrange_attachment(self):
self.attachments = [
{
"fallback": "Required plain-text summary of the attachment.",
"color": "#2eb886",
"fields": [
{
"value": self.title+"\n"+self.title_ja+"\n"+self.url,
"short": False
}
],
"image_url": "http://my-website.com/path/to/image.jpg",
"thumb_url": "http://example.com/path/to/thumb.png",
}
]
for one_entry in rss.entries:
try:
# Entryのクラスを作成
entry = Entry(one_entry)
# 翻訳
entry.translate()
# slackに送る情報(attachment)を作成
entry.arrange_attachment()
attachments = entry.attachments.copy()
# 通知する
slack.notify(attachments=attachments)
#接続エラーやロボット検出があればストップ(多分問題なし)
except:
break
slackのwebhookに情報を渡すにはslack.notifyという関数を利用しますが、ここでattachmentsという引数に通知したい情報を辞書形式で渡します。
このattachmentの書き方の詳細はslack webhook公式ページからみれます。
これでSlackに通知がくるかと思います!
(しかし通知がうるさいので、通知音やホーム画面への通知は切っておくことをオススメします笑)
#cron
ここまででarxivの新着情報をpythonによってslackに送ることができました。
次はcronというデーモンプログラムで時間や日付を指定して、バックグラウンドで先ほど作ったarxivbot.pyを実行させます。ちなみにwikiによるとデーモンという言葉はdemon(悪魔)とdeamon(守護神)の2通りの書き方が使われてるみたいですね。厨二でかっこいい()
やることは非常に簡単で、
crontab -e
でcronの設定ファイルを開き、
0 9 * * * {pythonのpath} {arxiv_botのpath}
と書くだけです。
ここで、{pythonのpath}は
which python
の結果で、{arxiv_botのpath}はarxiv_botの絶対PATHです。
0 9 * * * というのは
0分 9時 *日 *月 *年ということで、つまり毎日9時0分に実行するということになります。
これが出来ればbotの作成が終了です。お疲れ様でした。