Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What are the problem?
@Hiroaki-K4

CVPR2020の論文を毎日自動で送ってくれるslack botを作ってみた!

経緯

最近はCVPR2020の論文の要約を読んで、面白そうな論文はmendeleyにストックするという作業をやっています。その作業が結構大変です。理由は以下の通りです。

  • 採択されている論文が多い(1500ぐらいだったような)
  • あんまり興味がない論文が結構ある。Adversarial attacksの防御論文多すぎ(笑)。
  • わからない英単語が結構あるので、google翻訳でその都度調べる

このような理由でどうにか作業をもっと簡単にしたいと思い、以下のようなシステムを作ることにしました。

プログラムの手順

  1. スクレイピングでCVPR2020の公式サイトから論文のタイトル要約pdfのリンクを取ってくる。
  2. 要約を和訳する。
  3. 要約の中で、あまり興味がない内容の単語が入っている場合は別にする。今回はAdversarial attacks系の論文。
  4. 論文のタイトル、要約、要約を和訳したもの、pdfのリンクを1時間おきにslackのチャンネルに自動で配信する

手順ごとに自分の実装を説明していきます。

1. スクレイピング

def main():
    # CVPR2020のサイト情報を取得
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"
        }
    url_name = "https://openaccess.thecvf.com/CVPR2020"
    url = requests.get(url_name, headers)
    soup = BeautifulSoup(url.content, "html.parser")
    # 論文情報がdtダグの中にあるのでその情報を取得する
    elems = soup.find_all("dt")
    for elem in tqdm(elems):
        url = elem.next.next.attrs['href']
        ori_link = "https://openaccess.thecvf.com/"
        contents_url = ori_link + url
        paper_link = requests.get(contents_url, headers)
        paper_soup = BeautifulSoup(paper_link.content, "html.parser")
        title = paper_soup.find('div', id="papertitle").text
        abstract = paper_soup.find('div', id="abstract").text

beautfulsoupを使っています。CVPRの論文はサイト上で以下のような感じで並んでいます。
Screenshot from 2020-07-19 20-46-04.png
それぞれのタイトルをクリックするとその論文の詳細ページに飛びます。
Screenshot from 2020-07-19 20-48-10.png
このページから論文のタイトル、要約、pdfのリンク(下のリンク)をスクレイピングします。

2. 要約の和訳

abstract_ja = translator.translate(abstract, src='en', dest='ja')
abstract_ja = str(abstract_ja.text)

googletransを使いました。こちらを参考にしました。

3. Adversarial attacksの排除

def sort_class(abstract):
    sentence = abstract
    adversarial_1 = re.search("adversarial attacks", sentence)
    adversarial_2 = re.search("Adversarial Attacks", sentence)
    adversarial_3 = re.search("adversarial examples", sentence)
    adversarial_4 = re.search("Adversarial Examples", sentence)
    adversarial_5 = re.search("adversarial robustness", sentence)
    adversarial_6 = re.search("Adversarial Robustness", sentence)
    adversarial_7 = re.search("adversarial noise", sentence)
    adversarial_8 = re.search("Adversarial Noise", sentence)
    if adversarial_1 != None or adversarial_2 != None or adversarial_3 != None or adversarial_4 != None or adversarial_5 != None or adversarial_6 != None or adversarial_7 != None or adversarial_8 != None:
        class_name = "adver"
        return class_name
    else:
        class_name = "other"
        return class_name

ちゃんと正規表現をやればもっと簡単にできると思います。今回は馬鹿正直に候補を全て書きました。adversarial attacksの論文は別のチャンネルに上げるようにします。

4. slackに自動配信

slackwebを使いました。使い方をこちらを参考にしました。コード全体を下にまとめます。

post_to_slack.py
import re
import time
import slackweb
import requests
from tqdm import tqdm
from bs4 import BeautifulSoup
from googletrans import Translator
translator = Translator()


def sort_class(abstract):
    sentence = abstract
    adversarial_1 = re.search("adversarial attacks", sentence)
    adversarial_2 = re.search("Adversarial Attacks", sentence)
    adversarial_3 = re.search("adversarial examples", sentence)
    adversarial_4 = re.search("Adversarial Examples", sentence)
    adversarial_5 = re.search("adversarial robustness", sentence)
    adversarial_6 = re.search("Adversarial Robustness", sentence)
    adversarial_7 = re.search("adversarial noise", sentence)
    adversarial_8 = re.search("Adversarial Noise", sentence)

    # 対象の単語がある場合は別にしておく
    if adversarial_1 != None or adversarial_2 != None or adversarial_3 != None or adversarial_4 != None or adversarial_5 != None or adversarial_6 != None or adversarial_7 != None or adversarial_8 != None:
        class_name = "adver"
        return class_name
    else:
        class_name = "other"
        return class_name


def main():
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"
        }
    url_name = "https://openaccess.thecvf.com/CVPR2020"
    url = requests.get(url_name, headers)
    soup = BeautifulSoup(url.content, "html.parser")
    elems = soup.find_all("dt")
    for elem in tqdm(elems):
        url = elem.next.next.attrs['href']
        ori_link = "https://openaccess.thecvf.com/"
        contents_url = ori_link + url
        paper_link = requests.get(contents_url, headers)
        paper_soup = BeautifulSoup(paper_link.content, "html.parser")
        title = paper_soup.find('div', id="papertitle").text
        abstract = paper_soup.find('div', id="abstract").text
        abstract_ja = translator.translate(abstract, src='en', dest='ja')
        abstract_ja = str(abstract_ja.text)
        pdf = paper_soup.find("dd").find("a").attrs['href'][6:]
        pdf_link = ori_link + pdf
        class_name = sort_class(abstract)

        attachments_title = []
        attachments_contents = []
        paper_title = {"title": title,
                "text": pdf_link}
        paper_contents = {"title": abstract,
                "text": abstract_ja}
        attachments_title.append(paper_title)
        attachments_contents.append(paper_contents)

        # adversarial attacksとその他の論文で分けてslackに通知する
        if class_name == "adver":
            slack = slackweb.Slack(url="YOUR_TOKEN")
            slack.notify(attachments=attachments_title)
            slack.notify(attachments=attachments_contents)
        else:
            slack = slackweb.Slack(url="YOUR_TOKEN")
            slack.notify(attachments=attachments_title)
            slack.notify(attachments=attachments_contents)

        time.sleep(3600)


if __name__ == "__main__":
    main()

完成したslack bot

Screenshot from 2020-07-19 21-09-06.png
論文のタイトル、pdfのリンク先、要約、要約を和訳したものの順で並んでいます。これが1時間ごとに自動で配信されます。herokuにデプロイしました。

感想

スクレイピングめっちゃ楽しかったです。ちょっとハマりそうです(笑)。ちなみにこちらに今回のCVPRの論文も含めた様々な論文のチャンネルがあるslackのworkspaceを作ったので、お気軽に参加してください。コードの中でおかしいところとかありましたらコメントください。

間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?