スクレイピングした情報や画面キャプチャをSlackに投稿するBot

# 1. 概要

Qiitaのマイページにある情報をスクレイピングしたり、画面キャプチャを撮ってSlackに投稿するBotをPythonで作ったので、覚書でのために投稿します。Pythonでコードを書くだけでできる簡単なBotです。

## 今回作るBotでできること
- 特定のキーワードを検知したら、Webページからスクレイピングした情報をSlackにポストする。
- 特定のキーワードを検知したら、Webページの画面キャプチャを撮り、画像をSlackにポストする。

## 作った背景
Qiitaに投稿した記事のいいね数が画面を開かなくてもわかるといいなと思って作りました。

## 環境

<img width="577" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/1e068c4f-4d9a-98ca-a041-1a79c6e795af.png">

- Python 3.7.3
- slackclient 2.1.0 
- urllib3 1.25.3
- beautifulsoup4 4.7.1
- selenium 3.141.0

では早速Botを作る手順を紹介します。

# 2. SlackのBotを作ってAPIトークンを設定する

[このURL](https://my.slack.com/apps/manage/custom-integrations)にアクセスし、SlackのBotを作成してAPIトークンをコピペします。
APIトークンはBotの編集画面から確認できます。
<img width="1034" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/f1653ee2-4e95-96fd-acf7-24270b8ccdec.png">

続いて、コピペしたSlackbotのAPIトークンを環境変数に設定します。

```
export SLACK_TOKEN='APIトークン'
```

# 3. 必要なライブラリをインストールする

## slackclient

slackclientとは、PythonでSlackAPIを扱えるようにするためのライブラリです。

```
$ pip3 install slackclient
```

## BeautifulSoup
BeautifulSoupとは、Pythonでスクレイピング（Webサイトからデータを取得して任意の情報を抽出）するのに便利なライブラリです。

```
$ pip3 install beautifulsoup
```

## selenium
Seleniumとは、Webブラウザを遠隔操作できるライブラリです。遠隔操作で、URLを開く、クリックする、スクロールする、文字を入力する、画面キャプチャを撮るなどの操作を行えます。

```
$ pip3 install selenium
```

# 4. 作業場所を作成し挨拶botで動作確認

作業場所はとてもシンプルです。 

```
bot
└── qiita.py
```

作業場所ができたら、動作確認をするために簡単な挨拶botを作ってみましょう。
`Hello`という文字を検知したらメンション付きで反応してくれるボットです。

```qiita.py
import os
import slack

# メッセージイベントとqiitabotをリンク
@slack.RTMClient.run_on(event='message')

def hellobot(**payload):
    data = payload['data']
    web_client = payload['web_client']
    rtm_client = payload['rtm_client']

    # Hello という文字を検知したら処理を開始
    if 'Hello' in data['text']:
        # 文字を検知したチャネルを取得
        channel_id = data['channel']
        # 投稿したユーザーを取得
        user = data['user']
        # 文字を検知したチャネルにメッセージを投稿
        web_client.chat_postMessage(
            channel=channel_id,
            # 投稿したユーザーにメンション
            text=f"""
                Hi <@{user}>!
            """
        )

# Botを起動する
slack_token = os.environ['SLACK_TOKEN']
rtm_client = slack.RTMClient(token=slack_token)
rtm_client.start()
```

コードを書いて保存したら、Botを起動しましょう。

```
$ python3 qiita.py
```

Botが起動したら、Helloと投稿してみましょう。
メンション付きで返信してくれたら成功です。

<img width="649" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/85eb514b-5f18-b321-4ef9-aafdf9e4325c.png">


#5. スクレイピングした情報をSlackに投稿するBotを作る

それでは準備が整ったので、Qiitaからスクレイピングした情報をSlackに投稿するBotを作ります。スクレイピングする情報は赤枠で囲ったあたりにある情報です。
<img width="1158" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/dd1fde75-db9f-bf71-68bf-08cd3873590f.png">

## Botの機能

- Slackで`qiita リスト`という投稿を検知
- Qiitaユーザー情報 > 投稿一覧 > 1P目から`記事名`、`記事URL`、`いいね数`をスクレイピングする
- スクレイピングした情報をSlackに投稿する


## コード
それではコードを書いていきます。

[BeautifulSoup](#beautifulsoup)とurllibを追加でインポートしてください。

```qiita.py
import urllib.request as req
from bs4 import BeautifulSoup
```
先ほど作成した挨拶botの記述(`def qiitabot(**payload):`以下のブロック)を削除し、新しいボットの記述を追加します。

```qiita.py
def qiitabot(**payload):
    data = payload['data']
    web_client = payload['web_client']
    rtm_client = payload['rtm_client']

    url = 'https://qiita.com/qiita'
    res = req.urlopen(url)
    soup = BeautifulSoup(res, 'html.parser')
    list = soup.select('.media.ItemLink')

    if 'qiita リスト' in data['text']:
        channel_id = data['channel']

        for li in list:
            t = li.select_one(".ItemLink__title")
            title = t.string
            a = t.a
            href = a.attrs["href"]
            likelist = li.select(".ItemLink__status li")
            info = li.select_one(".ItemLink__info").text
            for i in likelist:
                i = 1
                likenum = likelist[0].text  

            web_client.chat_postMessage(
                channel=channel_id,
                text=f"""
:+1:*{likenum}* いいね！ {info}
> {title}
> https://qiita.com{href}
                """
            )
```
コードを書いて保存したら、Botを起動します。

```
$ python3 qiita.py
```

Botが起動したら、`qiita リスト`と投稿してみましょう。SlakにQiitaの記事を投稿してくれたら成功です。

<img width="633" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/0d89115d-417c-ae8c-b82a-ea20c3f79282.png">

#6. 画面をキャプチャし画像をSlackに投稿するBotを作る
続いて、Qiitaのページを画面キャプチャしSlackに投稿するBotを作ります。キャプチャするのは以下の画面です。

![file.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/8f56c656-00d9-4329-b1c0-5638f052c7b5.png)

## Botの機能

- Slackで`qiita キャプチャ`という投稿を検知
- `Qiitaユーザー情報の画面をキャプチャする
- キャプチャした画像をSlackに投稿する
※Firefoxで画面をキャプチャするので、Firefoxがインストールされていることが前提です。

## コード
それではコードを書いていきます。
[selenium](#selenium)を追加でインポートしてください。

```qiita.py
from selenium.webdriver import Firefox, FirefoxOptions
```
続いてコードを書いていきます。
前述の「スクレイピングした情報をSlackに投稿するBot」の`if`文に`elif`で追加します。

```qiita.py
elif 'qiita キャプチャ' in data['text']:
    channel_id = data['channel']
    options = FirefoxOptions()
    options.add_argument('-headless')
    browser = Firefox(options=options)
    browser.get(url)
    browser.save_screenshot("qiita-mypage.png")
    web_client.files_upload(
        channels=channel_id,
        file="qiita-mypage.png"
    )
```
コードの全文は以下です。

```qiita.py
import os
import slack
import urllib.request as req
from bs4 import BeautifulSoup
from selenium.webdriver import Firefox, FirefoxOptions

@slack.RTMClient.run_on(event='message')

def qiitabot(**payload):
    data = payload['data']
    web_client = payload['web_client']
    rtm_client = payload['rtm_client']

    url = 'https://qiita.com/qiita'
    res = req.urlopen(url)
    soup = BeautifulSoup(res, 'html.parser')
    list = soup.select('.media.ItemLink')

    if 'qiita リスト' in data['text']:
        channel_id = data['channel']
        for li in list:
            t = li.select_one(".ItemLink__title")
            title = t.string
            a = t.a
            href = a.attrs["href"]
            likelist = li.select(".ItemLink__status li")
            info = li.select_one(".ItemLink__info").text
            for i in likelist:
                i = 1
                likenum = likelist[0].text  

            web_client.chat_postMessage(
                channel=channel_id,
                text=f"""
:+1:*{likenum}* いいね！ {info}
> {title}
> https://qiita.com{href}
                """
            )

    elif 'qiita キャプチャ' in data['text']:
        channel_id = data['channel']
        options = FirefoxOptions()
        options.add_argument('-headless')
        browser = Firefox(options=options)
        browser.get(url)
        browser.save_screenshot("qiita-mypage.png")
        web_client.files_upload(
            channels=channel_id,
            file="qiita-mypage.png"
        )

slack_token = os.environ['SLACK_TOKEN']
rtm_client = slack.RTMClient(token=slack_token)
rtm_client.start()
```
コードを書いて保存したら、Botを起動します。

```
$ python3 qiita.py
```

Botが起動したら、`qiita リスト`と投稿してみましょう。作業場所にキャプチャした画像が保存され、Slackにファイルを投稿してくれたら成功です。
※2回目以降は生成した画面キャプチャは新しいものに置き換えらます。
※投稿まで少し時間がかかります。(数十秒くらい)

```
bot
├── qiita.py
└── qiita-mypage.png
```

<img width="631" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152545/3bcd2bf2-13b0-74fe-8af9-0008857f2c59.png">

# 7. さいごに
はじめてPythonを使いました。
いろいろ機能が豊富で面白いので、もっと勉強しようと思います。

# 8. 参考文献
[Github: python-slackclient](https://github.com/slackapi/python-slackclient)
[書籍: Pythonによるスクレイピング&機械学習](https://www.amazon.co.jp/dp/4802610793)