コロナでコロコロ変わる新入生情報の更新通知作ったった

# どーでもいい背景
大学決まりました。
春からの新生活に思いをはせてたら
**大学「コロナだから授業延期するわ。入学式もなくすわ。新入生特設サイトに情報乗っけるからマメに確認しろよ」**
ということで5月くらいまで授業ないです

さて、せっかくの長期休みなので勉強でもします
けれどここで一つだけ気をつけるべきことがあります

**大学「新入生特設サイトに情報乗っけるからマメに確認しろよ」**
↑これです
新入生なので情報逃すのは結構きついです
なのでちゃんと更新は確認しないといけません
でも毎日毎日Website見るのはめんどくさくてやってらんね
じゃあもうお分かりですね
そうです、更新通知を作ります
~~というか大学側もChromeの通知機能使って更新通知くらいしてくれよ~~

今回は[早稲田大学 新入生情報サイト](https://www.waseda.jp/fsci/news/2020/03/04/13353/)で作っていきましょう

# 更新通知を作っていく
## やりかた
まずどうやって通知の機能を作るか考えていきましょう

1. スクレピングで最新のサイトの状態をとってくる
2. 昨日のサイトと比較する
3. 変化してたら更新されたということにする
4. 更新の通知(tweetする)

こんなところです
シンプルですね

## ファイル構成
.
├── info.txt
├── main.py
└── tweet.py


## 作る前に
スクレイプする予定なのでまず[robots.txt](https://qiita.com/nezuq/items/c5e827e1827e7cb29011)の存在を確認します
robots.txtがない場合でも常識を弁えた程度にしましょう
今回作るのは1日に1回程度なので負荷はそんなに大きくないですね
今回のサイトではrobots.txtはありませんでした
https://www.waseda.jp/robots.txt
↑404ですね

例としてとりあえず他の大学のrobots.txtでも置いときます
興味ある人は中身覗いてみてください
- [東大のrobots.txt](https://www.u-tokyo.ac.jp/robots.txt)
- [慶應大学のropbots,txt](https://www.keio.ac.jp/robots.txt)
東大は設定されてますね
慶應は空だけどファイルはありますね
早稲田もrobots.txtくらい設定しとけよ

次にサイトの中でアクセスポリシーなどをみていきます
[accesibility-and-copyright](https://www.waseda.jp/top/accesibility-and-copyright)
一応プライバシーポリシーなどもみていきます
[privacy-policy](https://www.waseda.jp/top/privacy-policy)

ここでサイトのクロールなどに関して書いてある場合はちゃんと読みましょう
ダメだと書いてあったらスクレイプしないでください

スクレピングの裁判事例などもあるのでそこらへんはしっかりしましょう
[Librahack事件](https://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6)


## 更新確認のプログラム作っていく
今回は簡単にPythonでチャチャっとやっていきます
スクレイプにはChromedriver使います
入ってなければhomebrewとかで入れてください

### 1回目(失敗)
まずWebsiteの情報を取ってきます
bs4で取ってこようとしたら動的に生成されるタイプだったのか失敗しました
特に悩む気もないのでseleniumで対応しました

### 2回目(成功)
わざわざサイト全部の情報抜いてくる必要もないので更新についてのところだけCSSselectorで抜いていきます
<details><summary>サンプルコード</summary><div>

```main.py
import os
import datetime

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

f_path = 'info.txt'
tweet_text = '【早稲田大学　新入生特設サイト】\n'
options = Options()
options.set_headless(True)
driver = webdriver.Chrome(chrome_options=options)
url = 'https://www.waseda.jp/fsci/news/2020/03/04/13353/'

# read saved info
if os.path.exists(f_path):
    with open(f_path) as f:
        old_info = f.read()
else:
    old_info = ''

# get latest info
driver.get(url)
html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, "html.parser")
latest_info = driver.find_element_by_css_selector(
    '#anc_pagetop > div.wrap-outer > div > div.post.soft-double-bottom.global-bg.container-outer > div > div > div.col-sm-9.eq.bg-white > div.bg-white.soft-double.post-body.wp-text > p:nth-child(1) > span').text

# comparison info
if latest_info == old_info:
    print('keep info')
    tweet_text += f'''{datetime.datetime.now()}現在において更新はありません
{url}
'''
else:
    print('change info')
    tweet_text += f'''{datetime.datetime.now()}現在、更新を確認しました
    WebSiteを確認してください
    {url}
    '''
    with open(f_path, mode='w') as f:
        f.write(latest_info)

```
</div></details>

取ってきた情報はこんな感じでinfo.txtに保存されます
<details><summary>info.txt</summary><div>

```
[最終更新日]
2020/3/25 2020年度授業開始日程について追加しました。
2020/3/24 学科専攻Majorガイダンス一覧を公開しました。
2020/3/19 学生証配付日程および奨学金関連手続きについて追加しました。
2020/3/17 [学部／日本語学位／正規生の皆さんへ]
WEB出願システム登録メールアドレスにお知らせを送信しました。
2020/3/16 英語プレイスメント試験（WeTEC）受験ページおよび受験ガイドを公開しました。
2020/3/13 英語プレイスメント試験（WeTEC）受験期間および学生定期健康診断について追加しました。
2020/3/12 科目登録日程について更新しました。
2020/3/5 WasedaIDについて追加しました。
2020/3/4 ページを公開しました。
```

</div></details>

## 通知機能のプログラムを作っていく
通知機能はいろいろありますね
GmailのAPIあたりたたいてもいいんですけど今回はTwitterAPIででもやっていきましょう
APIの取り方は[過去記事](https://qiita.com/nya3_neko2/items/d801a7b47d335a643cfa)でも補助にしてさくっと取ってみてください
けっこう遊べて楽しいですよ

まずKeyとかの設定とかするファイルだけ作っちゃいます
tweetの関数とかも入れときましょう
<details><summary>tweet.py</summary><div>

```python
import tweepy

CONSUMER_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
CONSUMER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxJ"
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ACCESS_TOKEN_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)


def tweet(string):
    api.update_status(status=string)

```

</div></details>

## 更新確認と通知機能をまとめましょう
最終的にこんな感じですね
<details><summary>main.py</summary><div>

```python
import os
import datetime

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

import tweet as tw

f_path = 'info.txt'
tweet_text = '【早稲田大学　新入生特設サイト】\n'
options = Options()
options.set_headless(True)
driver = webdriver.Chrome(chrome_options=options)
url = 'https://www.waseda.jp/fsci/news/2020/03/04/13353/'

# read saved html
if os.path.exists(f_path):
    with open(f_path) as f:
        old_info = f.read()
else:
    old_info = ''

# get latest info
driver.get(url)
html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, "html.parser")
latest_info = driver.find_element_by_css_selector(
    '#anc_pagetop > div.wrap-outer > div > div.post.soft-double-bottom.global-bg.container-outer > div > div > div.col-sm-9.eq.bg-white > div.bg-white.soft-double.post-body.wp-text > p:nth-child(1) > span').text

# comparison html
if latest_info == old_info:
    print('keep info')
    tweet_text += f'''{datetime.datetime.now()}現在において更新はありません
{url}
'''
else:
    print('change info')
    tweet_text += f'''{datetime.datetime.now()}現在、更新を確認しました
    WebSiteを確認してください
    {url}
    '''
    with open(f_path, mode='w') as f:
        f.write(latest_info)
print(tweet_text)
tw.tweet(tweet_text)

```

</div></details><details><summary>tweet.py</summary><div>

```python
import tweepy

CONSUMER_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
CONSUMER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxJ"
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ACCESS_TOKEN_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)


def tweet(string):
    api.update_status(status=string)

```

</div></details>

## 実験
実際にやるとこんな感じ
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【早稲田大学　新入生特設サイト】<br>2020-03-26 23:44:13.217527現在において更新はありません<a href="https://t.co/nm9QSo8ZC2">https://t.co/nm9QSo8ZC2</a></p>&mdash; 電電⚡️猫猫 (@nya3_neko2) <a href="https://twitter.com/nya3_neko2/status/1243187002628919296?ref_src=twsrc%5Etfw">March 26, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# おわりー
このコードをcronで定期的に実行するとか、AWSとかにのっけて自動化することもできますね
AWSの１年無料期間終わっちゃったから僕はしないとおもうので誰かやってくれないかな
じゃあ新入生の皆さん、新しい情報を見逃さず良いキャンパスライフを！

最後に
スクレピングは常識的にやりましょう
このコードを試すのは自己責任です

# 参考
- [Python Webスクレイピング テクニック集「取得できない値は無い」](https://qiita.com/Azunyan1111/items/b161b998790b1db2ff7a#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
- [Python Webスクレピング　実践入門](https://qiita.com/Azunyan1111/items/9b3d16428d2bcc7c9406)
- [Webスクレイピングの注意事項一覧](https://qiita.com/nezuq/items/c5e827e1827e7cb29011)