Try   HackMD

<第10回Web会議日程>
2024年08月21日(水)19:00から

第9回 課題

・課題

以下のように、LINEに位置情報を送信した場合、
HotpepperAPIを利用し、画像やその他の情報と合わせて
おすすめのお店を1軒紹介するよう処理を追加してください

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

・回答例 「lambda_function.py

※一部抜粋

def lambda_handler(event, context): ​ logger.info(json.dumps(event)) ​ to_text = '' # ~省略~# 第9回課題# LINEで文字列が入力された場合if json.loads(event['body'])['events'][0]['message']['type'] == 'text': ​ ​ # 入力メッセージを取得 ​ from_text = json.loads(event['body'])['events'][0]['message']['text'] ​ ​ # from_text 値チェック ​ logger.info('from_text:{}'.format(from_text)) ​ ​ # 第6回課題 ​ ​ if from_text == 'おはよう': ​ to_text = 'おはよう!'elif from_text == 'こんにちは': ​ to_text = 'こんにちは!'elif from_text == 'こんばんは': ​ to_text = 'こんばんは!'# 第7回課題# LINEで入力内容が「入力」から始まった場合elif from_text.startswith('入力'): ​ # s3_functionモジュールのs3_input関数を呼び出す ​ to_text = s3_function.s3_input(from_text) ​ ​ # LINEで入力内容が「出力」から始まった場合 elif from_text.startswith('出力'): ​ # s3_functionモジュールのs3_output関数を呼び出す ​ to_text = s3_function.s3_output(from_text) ​ # 第8回課題# LINEで入力内容が「ホットペッパー」から始まった場合elif from_text.startswith('ホットペッパー'): ​ # hotpepper_functionモジュールのshop_search関数を呼び出す ​ to_text = hotpepper_function.shop_search(from_text) ​ ​ else: ​ to_text = '定義されていないメッセージです。'# 第9回課題# LINEで位置情報が入力された場合else: ​ latitude = json.loads(event['body'])['events'][0]['message']['latitude'] ​ longitude = json.loads(event['body'])['events'][0]['message']['longitude'] ​ ​ # latitude,longitude 値チェック ​ logger.info('latitude:{}'.format(latitude)) ​ logger.info('longitude:{}'.format(longitude)) ​ ​ to_text = hotpepper_function.shop_search_map(latitude,longitude) ​ ​ # to_text 値チェック ​ logger.info('to_text:{}'.format(to_text)) # ~省略~

・解説 「lambda_function.py

①位置情報が入力された場合の処理

文字列が入力された場合、これまで通りの処理をする必要があるため、
LINEの入力内容が文字列かどうか判定するIF文を追加し、
「from_text」を取得し「to_text」を定義する処理のインデントを下げる

# 第9回課題
# LINEで文字列が入力された場合
if json.loads(event['body'])['events'][0]['message']['type'] == 'text':
 
    # 入力メッセージを取得
    from_text = json.loads(event['body'])['events'][0]['message']['text']
    
    # from_text 値チェック
    logger.info('from_text:{}'.format(from_text))
    
    # 第6回課題
    
    if from_text == 'おはよう':
        to_text = 'おはよう!'
    elif from_text == 'こんにちは':
        to_text = 'こんにちは!'
    elif from_text == 'こんばんは':
        to_text = 'こんばんは!'

LINEの入力内容が文字列でない場合(位置情報の場合)、
「from_text」ではなく、緯度経度を取得する

# 第9回課題
# LINEで位置情報が入力された場合
else:
    latitude  = json.loads(event['body'])['events'][0]['message']['latitude']
    longitude = json.loads(event['body'])['events'][0]['message']['longitude']

② 「hotpepper_function.py」呼び出し処理

「latitude」「longitude」を引数とする
shop_search_map関数を呼び出し、結果を「to_text」に代入

to_text = hotpepper_function.shop_search_map(latitude,longitude)

・回答例 「hotpepper_function.py

※一部抜粋

# ~省略~ def shop_search_map(latitude,longitude): ​ #《1.HotpepperAPIにリクエストを送信》# HotpepperAPIへのリクエストパラメータ準備 ​ hp_pram = { ​ 'key':HP_API_KEY, ​ 'lat':latitude, ​ 'lng':longitude, ​ 'order':4, ​ 'count':1, ​ 'format':'json' ​ } ​ # hp_pram 値チェック ​ logger.info('hp_pram:{}'.format(hp_pram)) ​ # HotpepperAPIにリスクエスト ​ response = requests.get(HP_URL,hp_pram) ​ #《2 . レスポンスからお店の情報を取得# response 値チェック ​ logger.info('response:{}'.format(response)) ​ ​ # レスポンスを辞書型に変換 ​ response_dict = response.json() ​ ​ # response_dict 値チェック ​ logger.info('response_dict:{}'.format(json.dumps(response_dict,indent=2,ensure_ascii=False))) ​ ​ # JSONデータの中からお店の名前を取得 ​ shopname = response_dict['results']['shop'][0]['name'] ​ ​ # 第8回課題 ​ genrename = response_dict['results']['shop'][0]['genre']['name'] ​ mobile_access = response_dict['results']['shop'][0]['mobile_access'] ​ catch = response_dict['results']['shop'][0]['catch'] ​ photo = response_dict['results']['shop'][0]['photo']['pc']['l'] ​ to_text = [shopname,genrename,mobile_access,catch,photo] ​ ​ return to_text

・解説 「hotpepper_function.py

「latitude」「longitude」を 引数とするshop_search_map関数を追加

def shop_search_map(latitude,longitude):

HotpepperAPIへのリクエストパラメータ「hp_param」に
「latitude」「longitude」を定義

hp_pram = {
    'key':HP_API_KEY,
    'lat':latitude,
    'lng':longitude,
    'order':4,
    'count':1,
    'format':'json'
}

HotpepperAPIにリクエストを送信し、レスポンスを辞書型に変換。
必要な情報を「to_text」に代入する。
lambda_functionに返す部分は、shop_search関数と同じで問題ない

# JSONデータの中からお店の名前を取得
shopname = response_dict['results']['shop'][0]['name']
    
# 第8回課題
genrename = response_dict['results']['shop'][0]['genre']['name']        
mobile_access = response_dict['results']['shop'][0]['mobile_access']
catch = response_dict['results']['shop'][0]['catch']
photo = response_dict['results']['shop'][0]['photo']['pc']['l']

第10回 課題

・課題

天気予報Appを実行する「WeatherForecast.py」に
以下の情報を追加してください。
■風の強さ
■波の高さ
■最高気温、最低気温
■6時間毎の降水確率

<修正前>

image

<修正後>

image


・課題の概要

今回は、天気予報APIに対してリクエストを送信し、レスポンスの天気予報情報を、
Tkinterというライブラリで作成したGUI画面で返します。

予報日、予報を取得してGUI画面で返すところまでは作成済のため、
取得する情報を追加していただきます。


・修正箇所

1. 追加情報の取得

天気予報APIからのレスポンスを辞書型に変換した値が変数「response_dict」に格納されています。

ここから風の強さ、波の高さ、最高気温、最低気温、6時間毎の降水確率を
抜き出して、それぞれ変数に代入してください。

2.メッセージの修正

GUIに表示するメッセージは、変数「msg」で定義しています。
1.で取得した情報を追加する形で、変数「msg」を修正してください。


・天気予報API(livedoor 天気互換)について

<天気予報API(livedoor 天気互換)とは>
無料で天気予報を取得できるWebAPIを用意してくれているサイト

https://weather.tsukumijima.net/

以下のURLに地域別に定義されたCITYパラメータを追加してGETリスエストを送ると、JSON形式で天気予報の情報がレスポンスとして返される

https://weather.tsukumijima.net/api/forecast/city/○○

▼CITYパラメータの定義
https://weather.tsukumijima.net/primary_area.xml


・tkinterについて

<tkinterとは>

GUIPython からGUIを構築・操作するためのライブラリ、標準ライブラリの1つ
メインウィンドウにラベルやボタンなどのパーツ(ウィジェット)を配置して構築する

<メインウィンドウ>
GUIのベースとなるウィンドウそのもの
「Tk」クラスをインスタンス化することで生成できる
スクリプトの最後でループさせることで、スクリプトを終了させず、GUI操作の待機をさせることができる

<ラベル(Label)>
Tkinterに備わる文字を表示させるためのウィジェット
「Labal」クラスをインスタンス化して生成できる
オプションを設定することで、フォント・サイズ・太さなどを変更可能

<ボタン(Button)>
Tkinterに備わるボタンを生成するためためのウィジェット
「Button」クラスをインスタンス化して生成できる
オプションでボタンクリック時の動作を指定可能


▼天気予報Appのウィジェット配置イメージ


・requestsについて

<requestsとは>
HTTP通信用のPythonのライブラリ
GET、POST、PUTなどのメソッドが用意されている
今回は、天気予報APIにGETリクエストを送るために使用

外部モジュールのため、利用するにはインストールの必要がある

pip install requests

<GETメソッド>
requests.get(リクエスト送信先URL,リクエストパラメータ)

URLに対してGETリクエストを送ることができる
リスエストの結果が、Responseオブジェクトとして返される