はじめに
更新を検知してslackに投げるbotを作りたいな~と思ってよくわかんないながら試行錯誤しつつbotを作ってみたので、そのときにハマったことを色々紹介したいと思います。
前提として、私はエンジニアではなく色々知識が不足しており色々検索しながらツギハギで作ってみたので、不勉強なところや詳しい人から見たらもっとこうしたらいいのに…という点が多々あると思いますが、ああそういうハマり方したのね~こいつは、という感じで見ていただければ幸いです。
もちろん、こうしたらもっとよかったよ!というご指摘いただければ嬉しいです!
やり始めたのが半年くらい前なので、忘れてるところも多数で思い出しながら書いていきます。
やったこと
とあるサイト(掲示板のようなもの)の更新を任意の間隔で確認し、新着投稿があった場合はその内容をslackで投稿する、というものです。
完成までの段階はこんな感じでした。
- スクレイピングと更新検知部分作成
- slackbot作成
- AWS,EC2の準備・実行
スクレイピングと更新検知
文字化け対策
pythonくらいしか書けないのでスクレイピングはresponseとbeautifulsoupを使いました。
とりあえずググりながらまずスクレイピングしてみたら、文字化けしちゃいました。
response = requests.get(url, headers=headers, timeout=9.0)
html = response.text
soup = BeautifulSoup(html, 'html.parser')
どうやらエンコードが正しく取得できていないのが原因のようだったので、
response = requests.get(url, headers=headers, timeout=9.0)
response.encoding = response.apparent_encoding
html = response.text
soup = BeautifulSoup(html, 'html.parser')
として、取得したレスポンスからエンコードを明示してあげればよかったみたいです。
ちなみに、beautifulsoupを使う場合は、
response = requests.get("http://www.example.com/")
soup = BeautifulSoup(response.content, "lxml")
こんな感じにbeautifulsoupに任せちゃってもいいみたいです。
slackbotを作成
探り探りboltでbot作成、block kit builderを使うと便利
当時は色々ググりながらやってたのですが、日本語版ドキュメントからqiitaへのリンクが色々貼ってある良さげなやつ見つけたのでこれ見ながらやると良さそうですね。
(当時なかった気がする…)
色々参照にしながらboltを入れて、slack側の設定を進めます。
(当時の記憶が全然ないので、割愛します、まあ上のリンク見ればできるでしょ)
で、botもboltのpythonので書いていくのですが、このときモーダルを使いたかったので手で書くと面倒~と思ってたら、ポチポチやって作れるblock kit builderを見つけました。
モーダルに限らんと思いますけど、slackbot作るときはこれ使うと便利そうですね。
AWS,EC2の準備・実行
作ったスクリプトを手元で動かして、slackに乗っけるところまではいけたので、クラウドに乗っけたいと思います。
なぜかGCEでスクレイピングできない!
最初はAWSではなくGCPでやろうとしてました。
スクリプトが込み入ってきたので、まあGCEに乗っければええっしょということでこれまで作ったプログラム群を乗っけて実行してみました。
すると、ローカルと環境大差なくコードは一言一句同じなのに、なぜかうまくスクレイピングできない、という事象が発生しました。
調べていると、403が返ってきている模様。
いろいろ試してみるのですが、状況変わらず…
動作はしているのでマシンの環境はあまり影響ないので、あと違いはなんだろう、と考えたところ、国か????というところにたどり着きました。
試しに海外串通してページにアクセスしてみると、403。
どうやら海外アクセスを弾いてる模様。
無料枠でやろうとしていたので、一旦それを諦めて国内リージョンでやってみますが…ダメ。
IPで弾いているみたいです。
で、GCEは国内IPでの固定ができない模様…
しばらくローカルでbot動かしてましたが、不便なのでやはりクラウドでやりたい。
じゃあAWSだったらどうか、ということで調べてみると、こんな記事を発見。
AWSだとやりたいことができそうなので、AWSに切り替えることを決定しました。
ガチャで国内っぽいIPを引いて、それをインスタンスに割り当てると…無事スクレイピングできました!
なお、インスタンスに引いたIPを割り当てている間は無料でIP固定ができるのですが、来年2月から有料化する模様。
1ドル150円なので、一旦はそのまま使い続けようと思います。いじるのめんどいので
スポットインスタンスのほうが安いと思ってたら無料枠外だった
bot作成とは少し離れるのですが、当然オンデマンドよりもスポットインスタンスのほうが安いでしょ、と思ってイメージ作ったりしてスポットインスタンスでしばらく動かしてたら、何故か課金が発生。
無料枠対象なのはオンデマンドだけでした。
12ヶ月?経ったらオンデマンドの無料枠なくなるので、そうなったら改めてスポットインスタンスで運用します。
バックグラウンドで実行
これで無事EC2上で動くようになったのですが、繋げて画面出してないと動かないのはあんまり意味ないので、バックグラウンドで実行したい。
もっと言うと、EC2起動したらそのまま動くようにしたかった。
そしたら、nohup使うとターミナル閉じてもインスタンスが落ちなければ動くようなので採用。
nohup python3 app.py &
こんな感じのコマンドを仕込んで、さらにこのファイルをstartstop.serviceに入れたらインスタンス起動時にbot起動させることができました!
おわりに
bot出来上がったあとも色々バグ取りとかやってたのですが、それはだいぶスクレイピングのやり方がまずっている部分が大きいので割愛。
こんな感じで、slackのbot作ってEC2に乗っけました、という体験談的なやつだったので、なにか参考になれば幸いです。