Python3+BeautifulSoup4+Cloud Functionsで1時間で作るしいたけ占いBot

# はじめに

しいたけ占いという占いサイトをご存知でしょうか？
https://voguegirl.jp/horoscope/shiitake/

弊社では、よく当たると社長を筆頭に空前の大ブームを巻き起こしています。
毎週月曜日に更新され、LINEもあるけど、みんながみるSlackに流れてきたら嬉しいよね！といって一人で始めたら意外と簡単で1時間でできましたという話。

# 作ったもの

しいたけ占いの更新日時である月曜12時にSlackにスクレイピングした各星座の占い結果を流すだけ！
[しいたけ占いBotのGitHub](https://github.com/kazuki5555/clf_siitake_fortune)

# 環境

- Google Cloud Functions
- Google Cloud Scheduler
- Google Cloud Pub/Sub
- Python 3.7
- BeautifulSoup4 4.8.1
- slackweb 1.0.5

<img width="381" alt="スクリーンショット 2019-10-25 18.13.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251929/be1e15e6-df5f-a97e-6cff-ea8ff793b23b.png">

こんな感じになります。
名前は基本「siitake」で統一していきます。

# Cloud Schedulerの登録

<img width="559" alt="スクリーンショット 2019-10-25 18.24.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251929/659b80ba-2901-f67e-d4cb-e1580ef5f4dd.png">

しいたけ占いの更新頻度に合わせて毎週月曜日の12時からに設定します。
この後Pub/Subを呼ぶのでターゲットはPub/Sub、トピックは「siitake」にしておきます。

# Cloud Pub/Subの登録

<img width="298" alt="スクリーンショット 2019-10-25 22.24.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251929/80831c3a-a9c5-5302-75ab-f43b0c8a25f9.png">

このトピックを作成ボタンを押してSchedulerと合わせるように「siitake」というトピックIDで作成します。

# Cloud Functionsの作成

<img width="514" alt="スクリーンショット 2019-10-25 22.27.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251929/0bc70a1c-982e-56e6-7201-1335f9d95579.png">

上記のように、トリガーをCloud Pub/Sub、トピックを先ほど登録した「siitake」にして作成します。

# main.pyの作成

あらかじめ`slackweb`と`bs4`をインストールしておきます。

```bash
$ pip install bs4 slackweb
```

流れ

１. １２星座の英語のリストを用意する

```python
constellations = [
        "aries",
        "taurus",
        "gemini",
        "cancer",
        "leo",
        "virgo",
        "libra",
        "scorpio",
        "sagittarius",
        "capricorn",
        "aquarius",
        "pisces"
    ]

    constellations_kana = [
        "【おひつじ座】",
        "【おうし座】",
        "【ふたご座】",
        "【かに座】",
        "【しし座】",
        "【おとめ座】",
        "【てんびん座】",
        "【さそり座】",
        "【いて座】",
        "【やぎ座】",
        "【みずがめ座】",
        "【うお座】"
    ]
```

２. 今日の日付を取得。星座リストをループで回しながらベースのURLに各星座、日付を当てはめて`bs4`で毎回HTMLを取得

```python
    base_url = "https://voguegirl.jp/horoscope/shiitake/"
    date = dt.date.today()
    slack = slackweb.Slack(url=os.environ["SLACK_URL"])

    for c, c_kana in zip(constellations, constellations_kana):
        url = base_url + c + "/" + date.strftime("%Y%m%d") + "/"
```

３. bs4で毎回HTMLを取得し欲しい部分に当たる`class="a-text"`部分を得る

```python
for c, c_kana in zip(constellations, constellations_kana):
        url = base_url + c + "/" + date.strftime("%Y%m%d") + "/"
        res = requests.get(url)
        soup = BeautifulSoup(res.text)
        res.close()
        base_txt = soup.find("div", class_="a-text").text
```

４. Slackに送るメッセージに合わせてテキストを当て込み送信！

```python
    for c, c_kana in zip(constellations, constellations_kana):
        url = base_url + c + "/" + date.strftime("%Y%m%d") + "/"
        res = requests.get(url)
        soup = BeautifulSoup(res.text)
        res.close()
        base_txt = soup.find("div", class_="a-text").text
        txt = c_kana + "\n\n" + base_txt.strip() + "\n\n続きはこちら⇒ " + url
        slack.notify(text=txt)
```

# 実装

<details><summary>全コードは以下に省略</summary><div>


```python

import requests
import datetime as dt
import os
import slackweb
from bs4 import BeautifulSoup

def siitake(a, b):
    constellations = [
        "aries",
        "taurus",
        "gemini",
        "cancer",
        "leo",
        "virgo",
        "libra",
        "scorpio",
        "sagittarius",
        "capricorn",
        "aquarius",
        "pisces"
    ]

    constellations_kana = [
        "【おひつじ座】",
        "【おうし座】",
        "【ふたご座】",
        "【かに座】",
        "【しし座】",
        "【おとめ座】",
        "【てんびん座】",
        "【さそり座】",
        "【いて座】",
        "【やぎ座】",
        "【みずがめ座】",
        "【うお座】"
    ]

    base_url = "https://voguegirl.jp/horoscope/shiitake/"
    date = dt.date.today()
    slack = slackweb.Slack(url=os.environ["SLACK_URL"])

    for c, c_kana in zip(constellations, constellations_kana):
        url = base_url + c + "/" + date.strftime("%Y%m%d") + "/"
        res = requests.get(url)
        soup = BeautifulSoup(res.text)
        res.close()
        base_txt = soup.find("div", class_="a-text").text
        txt = c_kana + "\n\n" + base_txt.strip() + "\n\n続きはこちら⇒ " + url
        slack.notify(text=txt)
```
</div></details>

実装は上記になります。
これ以外に、

- Cloud Functionsの環境変数に`SLACK_URL`としてincoming webhookのURLを登録
- requirements.txtに`bs4`と`slackweb`を登録する必要があります。

# 結果

<img width="806" alt="スクリーンショット 2019-10-25 22.52.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251929/1138ea59-73dd-555e-c61f-7a9e5c3c9a60.png">

これを見てみんなでハッピーになりました。

# 感想とか

初めてCloud Functionsを使ったけどすごく簡単にできて楽しかった。 
また、Pythonでのスクレイピングも初めてだったけど、直感的で使いやすかった。
何より、何かを作るのは楽しいし、社内でみんな喜んでくれると嬉しい！