Q. Lambdaって、毎回.pyを実行するんじゃないの? A. ハンドラの「関数」を実行する
メッセージそれぞれに対して
print("message: ", message["text"], message["ts"], time.time() - float(message["ts"]))
と時間差を取得してみても、正しい時間差が取れていました。でも毎回同じメッセージを形態素解析してしまっています。
ということは、requests.getが毎回実行されていないかも知れません。ハンドラの関数内部だけが毎回実行されている仮説、つまりハンドラの外で実行していたrequestsである、
res = requests.get(get_url, headers=header, params=payload)
が初回実行時のみ実行されていたら、今起きていることと同じ結果になりそうです。
「lambda ハンドラ」で検索しPython の Lambda 関数ハンドラー - AWS Lambdaを読むと、「関数が呼び出されると、Lambda はハンドラーメソッドを実行します。」と書いてあります。確かにkanehosi_tukeai.pyファイル全体を実行するわけではなく、ハンドラであるpost_77_to_575関数だけを実行していそうです。
すると、可読性は落ちますが単に置き換えると以下のようになります。
import ipadic import jaconv import MeCab import re import requests import time m = MeCab.Tagger(ipadic.MECAB_ARGS) #形態素解析用objectの宣言 def post_message(thread_ts: str, header: dict[str, str], channel_id: str) -> None: data = { "channel" : channel_id,# Conversation IDを入れてください "text" : "それにつけても金の欲しさよ" } data["thread_ts"] = thread_ts post_url = "https://slack.com/api/chat.postMessage" requests.post(post_url, headers=header, data=data) def extract_hiragana(text: str) -> str: return "".join(re.findall(r'[ぁ-ゔー]', text)) def get_pronunciation_list(text: str) -> list[str]: m_result = m.parse(text).splitlines() #mecabの解析結果の取得 m_result = m_result[:-1] #最後の1行は不要な行なので除く pro: list[str] = [] #いい感じに切った読み全体を格納する変数 for v in m_result: if '\t' not in v: continue if v.split('\t')[1].split(",")[0] in ["記号"]: continue surface = v.split('\t')[0] #表層形 if len(v.split('\t')[1].split(",")) <= 7: continue p = v.split('\t')[1].split(",")[7] #読みを取得, 8は発音 if p == '*':#発音が取得できていないときsurfaceで代用 p = surface if v.split('\t')[1].split(",")[0] in ["助詞", "助動詞"] and pro: pro[-1] += p else: pro.append(p) pro = [jaconv.kata2hira(p) for p in pro] #ひらがなをカタカナに変換 pro = [extract_hiragana(p) for p in pro if p] #余計な記号を削除 return pro def is_575(text: str) -> bool: words = get_pronunciation_list(text) length = 0 reversed_expected_length_list = [5, 7, 5] for word in words: if not reversed_expected_length_list: # 575が終わったのにまだ続く return False length += len(re.sub(r'[ぁぃぅぇぉゃゅょ]', '', word)) # 1音を構成しない文字 if length == reversed_expected_length_list[-1]: length = 0 reversed_expected_length_list.pop() if reversed_expected_length_list: # 575と切り取れなかった return False return True def post_77_to_575(event, context) -> None: token = "xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxx..."# tokenを入れてください channel_id = "C0123456789",# Conversation IDを入れてください header={ "Authorization": "Bearer {}".format(token) } payload = { "channel" : channel_id, "limit": 20 } get_url = "https://slack.com/api/conversations.history" res = requests.get(get_url, headers=header, params=payload) json_channel_history = res.json() if "messages" not in json_channel_history: print("no message recentry, check token and channel ID") return for message in json_channel_history["messages"]: print("message: ", message["text"], message["ts"], time.time() - float(message["ts"])) if is_575(message["text"]) and time.time() - float(message["ts"]) <= 60: post_message(message["ts"], header, channel_id) return if __name__ == "__main__": post_77_to_575("", "")
もっと良い変数名などはあると思いますが、とりあえずこれで動きます。
Q. 今度こそ定期判定できてるの? A. スッコココ! それにつけても金の欲しさよ
おめでとうございます。これからずっと「句を詠めば鐘が鳴るなりスッコココ」です。満足するまでリファクタリングしましょう。今回は省きましたが、テスト駆動開発をしていれば、安心してリファクタリングできるはずです。
おわりに
全て読んでくれた人、特にありがとうございます。改めてAWS Lambda で形態素解析〜句を詠めば鐘が鳴るなりスッコココ〜 - estie inside blogを読んでみましょう。高速度合が分かります。そして、AWS Lambda で形態素解析〜句を詠めば鐘が鳴るなりスッコココ〜では分からなくて奥のほそみち編を読んで、読み返して高速道路編が理解できていれば、私はとてもうれしいです。
estieでは社員とSlackメッセージが増えていますがこれで自動的に判定してくれます。忙しい現代人に、つかの間の趣を与えてくれます。575判定的に社員が増えても問題なくなったので、575判定されたい方、1分かかるbotより早く575判定する私にも勝つ自信のある方、入社をお待ちしております。
今回はestieが扱うオフィス不動産の話を全くしていないので、不動産の話を聞きたい方もお待ちしております。お疲れ様でした。