こんにちは!Oisix ra daichiの平島です。
この業界に入ってから勉強の毎日で、まだまだ分からないことだらけですが、
業務効率化のために日々挑戦しています。
slack×pythonは 日々の業務の中で、データの件数に異常がないか確認するために利用しています。
今回はその実装方法を紹介します。
※個別のモジュールのインストールについては割愛しています。
slackのwebhook_urlを取得する
参考: api.slack.com ※Qiita等にわかりやすい記事があるので参考にしてください。
一番簡単なメッセージを投稿してみる
import requests import json incoming_webhook_url = "***" payload = json.dumps({ 'text': "私はトマトです", 'channel': "@user_name", 'username': "tomato", 'icon_emoji': ":tomato:" }) requests.post(incoming_webhook_url, data=payload)
このpythonファイルを実行すると、下記のようにメッセージが来ます。
データベースに接続する
cx_Oracleを使います。 参考:
cx_Oracle - Python Interface for Oracle Database
ユーザ名、パスワード、ホスト名、ポート番号、サービス名を入力しDBに接続する。
import cx_Oracle user = "" password = "" hostname = "" port = "" service_name = "" conn = cx_Oracle.connect(user, password, hostname + ':' + port + '/' + service_name, encoding="UTF-8", nencoding="UTF-8") cur = conn.cursor()
データベースからデータを取得する
今回は下記のようなテスト用テーブルを作成しました。
ID | FRUIT | PRICE |
---|---|---|
1 | りんご | 200 |
2 | ぶどう | 300 |
3 | みかん | 100 |
データを検索する。この際にpandasを使ってみようと思います。
pandasはDataFrameという強力なクラスを持っています。
RDBのようにデータを取り扱うことが可能で、並列計算ができるので処理も高速です。
import pandas as pd sql = "SELECT ID, FRUIT, PRICE FROM FRUIT_PRICE" cur.execute(sql) fruit_price_df = pd.DataFrame(cur.fetchall())
結果は以下のように返ってきます。これが今fruit_price_df に入ってい
0 | 1 | 2 | |
---|---|---|---|
0 | 1 | りんご | 200 |
1 | 2 | ぶどう | 300 |
2 | 3 | みかん | 100 |
列名が入っておらず扱いづらいため、列名を付与します。
fruit_price_df .columns = ["ID", "FRUIT", "PRICE"]
ID | FRUIT | PRICE | |
---|---|---|---|
0 | 1 | りんご | 200 |
1 | 2 | ぶどう | 300 |
2 | 3 | みかん | 100 |
slackに通知します
基本のテキストを用意します。{}には文字列を代入できます。
message_base = "{}の価格は{}円です。"
これをmessageにします。
message = "" for i in range(len(fruit_price_df.index)): message += "{}の価格は{}円です。\n".format(fruit_price_df["FRUIT"][i] , fruit_price_df["PRICE"][i]) #for index, rows in fruit_price_df.iterrows(): こういう書き方もできます。本当はこちらの書き方が良いです。 # message += "{}の価格は{}円です。\n".format(rows[1], rows[2])
これでmessageが完成したので、後は最初に用意した「私はトマトです」をmessageに置き換えるだけです。 一貫するとこうなります。
import requests import json import pandas as pd incoming_webhook_url = "***" import cx_Oracle user = "" password = "" hostname = "" port = '' service_name = "" conn = cx_Oracle.connect(user, password, hostname + ':' + port + '/' + service_name, encoding="UTF-8", nencoding="UTF-8") cur = conn.cursor() sql = "SELECT ID, FRUIT, PRICE FROM FRUIT_PRICE" cur.execute(sql) fruit_price_df = pd.DataFrame(cur.fetchall()) fruit_price_df.columns = ["ID", "FRUIT", "PRICE"] message = "" for i in range(len(fruit_price_df.index)): message += "{}の価格は{}円です。\n".format(fruit_price_df["FRUIT"][i] , fruit_price_df["PRICE"][i]) #for index, rows in fruit_price_df.iterrows(): # message += "{}の価格は{}円です。\n".format(rows[1], rows[2]) payload = json.dumps({ 'text': message, 'channel': "@user_name", 'username': "tomato", 'icon_emoji': ":tomato:" }) requests.post(incoming_webhook_url, data=payload)
弊社ではこのpythonファイルをcronではなくdigdagで実行しています。
digdagについての詳しい話はそのうち公開されますので、楽しみにしていてください。
おまけ
webhook urlだけでも、いろいろな表現ができます。
この時の
requests.post(incoming_webhook_url, data=payload)
payloadの中身を下記に記載しておきます。
{'attachments': [{'actions': [{'name': 'ボタンの名前です(表示はされない', 'style': 'primary', 'text': 'OISIX\u3000HP', 'type': 'button', 'url': 'ボタンのリンク'}], 'author_icon': 'アイコンの画像', 'author_link': 'アイコンの横の文字のリンク', 'author_name': 'oisix', 'color': 'good', 'fields': [{'short': True, 'title': '記事1', 'value': '<'埋め込みリンク'|あめトマト>'}, {'short': True, 'title': '記事2', 'value': '<'埋め込みリンク'|みつトマト>'}], 'footer': 'tomatoでした', 'footer_icon': 'フッターの画像(「tomatoでした」の左)のリンク', 'pretext': 'oisixの記事について、まとめました。', 'text': 'トマトを食べよう!', 'thumb_url': 'サムネイルのリンク(ミニトマト)', 'title': 'トマトのページ', 'title_link': 'タイトルのリンク', 'ts': 1544595510}], 'channel': '@user_name', 'icon_emoji': ':tomato:', 'link_names': 1, 'text': '私はトマトです<!here>', 'username': 'tomato'}
現在はbotを製作中です。また機会があれば書きたいと思います。
アドベントカレンダーにて、他のメンバーもブログを書いています!
ぜひご覧下さい!