Try   HackMD
tags: Python勉強会

【51期】Python勉強会 第9回

<第9回Web会議日程>
2024年07月18日(木) 19:00から

第8回 解説

・課題

現在、以下のようにLINEで入力した場合、2行目を検索キーワードとして、
HotpepperのグルメサーチAPIにリクエストを送信し、おすすめのお店を一軒紹介します

image

同様の入力をした場合に、お店の名前に加え、
付加情報をLINEに返すよう処理を追加してください

image

・回答例 「hotpepper_function.py

※一部抜粋

def shop_search(from_text): ​ #《1.HotpepperAPIにリクエストを送信》# 入力内容を改行コードで区切ってリスト型に格納str = from_text.split('\n') ​ # str 値チェック ​ logger.info('str:{}'.format(str)) ​ # リストの要素数が2つの場合if( len(str) == 2 ): # ~省略~# レスポンスを辞書型に変換 ​ 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回課題 ​ shopname = response_dict['results']['shop'][0]['name'] ​ genrename = response_dict['results']['shop'][0]['genre']['name'] ​ mobile_access = response_dict['results']['shop'][0]['mobile_access'] ​ catch = response_dict['results']['shop'][0]['catch'] ​ ​ to_text = [shopname,genrename,mobile_access,catch] ​ ​ else: ​ to_text = '2行目に検索キーワードを入力してください' ​ ​ return to_text

・解説 「hotpepper_function.py

① LINEに応答する付加情報を取得

「response_dict」から任意の情報を5つまで取得し、
それぞれ変数に代入する

shopname = response_dict['results']['shop'][0]['name']
genrename = response_dict['results']['shop'][0]['genre']['name']        
mobile_access = response_dict['results']['shop'][0]['mobile_access']
catch = response_dict['results']['shop'][0]['catch']

②「to_text」にリスト型で代入

1で取得したそれぞれの要素を [ ] で括り、
リスト型として、「to_text」に代入する

to_text = [shopname,genrename,mobile_access,catch]

・回答例 「lambda_function.py

※一部抜粋

# ~省略~ def lambda_handler(event, context): ​ # ~省略~   ​ # 第8回課題# to_textが文字列だった場合if type(to_text) is str: ​ params['messages'].append({}) ​ params['messages'][0]['type'] = 'text' ​ params['messages'][0]['text'] = to_text ​ # to_textが文字列以外の場合(リスト) else: ​ # enumerateでインデックスと要素を抽出してループ処理for no,item in enumerate(to_text): ​ params['messages'].append({}) ​ params['messages'][no]['type'] = 'text' ​ params['messages'][no]['text'] = item # ~省略~

・解説 「lambda_function.py

①「to_text」のデータ型

「to_text」が文字列だった場合の分岐を作成し、これまで通り、
リスト型「messages」内に、type、textのキーを持つ辞書を1つ定義する

if type(to_text) is str:
    params['messages'].append({})
    params['messages'][0]['type'] = 'text'
    params['messages'][0]['text'] = to_text

②「messages」への要素の追加

「to_text」が文字列ではない場合、リスト型のため、
リストのインデックスと要素をまとめて取り出せるenumerateを利用して
for文で、「messages」への要素の追加をループ処理させる

else:
    # enumerateでインデックスと要素を抽出してループ処理
    for no,item in enumerate(to_text):
        params['messages'].append({})
        params['messages'][no]['type'] = 'text'
        params['messages'][no]['text'] = item

<enumerate>
list.enumerate()
・リストに含まれている要素にインデックスを0から割り振り、「(インデックス, 要素)」というタプルにまとめた特殊なオブジェクトを返す


第8回 チャレンジ課題

※余力のある方向け

■ 課題

以下の入力をした場合に、お店の名前、付加情報に加え、お店の画像
をLINEに返すよう処理を追加してください

image


・回答例 「hotpepper_function.py

※一部抜粋

def shop_search(from_text): # ~省略~ ​ shopname = response_dict['results']['shop'][0]['name'] ​ 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] # ~省略~

・解説 「hotpepper_function.py

「response_dict」から 「店舗トップ写真(大)画像URL」 を取得し、「to_text」に代入する

photo = response_dict['results']['shop'][0]['photo']['pc']['l']

to_text = [shopname,genrename,mobile_access,catch,photo]

・回答例 「lambda_function.py

# ~省略~ def lambda_handler(event, context): # ~省略~   # 第8回課題 # to_textが文字列だった場合 if type(to_text) is str: params['messages'].append({}) params['messages'][0]['type'] = 'text' params['messages'][0]['text'] = to_text # to_textが文字列以外の場合(リスト) else: # enumerateでインデックスと要素を抽出してループ処理 for no,item in enumerate(to_text): # 抽出した要素が画像の場合(「jpg」で終わる)の処理 if item.endswith('.jpg'): params['messages'].append({}) params['messages'][no]['type'] = 'image' params['messages'][no]['originalContentUrl'] = item params['messages'][no]['previewImageUrl'] = item # 画像以外の処理 else: params['messages'].append({}) params['messages'][no]['type'] = 'text' params['messages'][no]['text'] = item # ~省略~

・解説 「lambda_function.py

to_textが文字列以外の場合のfor文内で、if文で分岐を作成し、画像の(「jpg」で終わる)場合、
リスト型「messages」内に、type、originalContentUrl、previewImageUrlの
キーを持つ辞書を定義する

画像ではなければ、type、textのキーを持つ辞書を定義する

        if item.endswith('.jpg'):
            params['messages'].append({})
            params['messages'][no]['type'] = 'image'
            params['messages'][no]['originalContentUrl'] = item
            params['messages'][no]['previewImageUrl'] = item
        else:
            params['messages'].append({})
            params['messages'][no]['type'] = 'text'
            params['messages'][no]['text'] = item

第9回 課題

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


・課題の概要

これまでは、LINEに文字列を入力しその内容に合わせて、
Lambda内で処理を実行させ、LINEに応答を返していました。

今回は、LINEに位置情報を入力し、緯度経度の情報をもとに
HotpepperAPIにリクエストを送信し、おすすめの店舗の情報を
返すよう処理を修正していただきます。


・「lambda_function.py」への修正

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

LINEで入力された内容は、その他の情報と合わせて変数「event」に格納されています。
その中から、以下の処理で、画像内の緑下線の入力メッセージを取得して「from_text」に格納して利用していました。

from_text = json.loads(event['body'])['events'][0]['message']['text']

■文字列が入力された場合の「event」の一部

位置情報が入力された場合は、以下の画像のようになります。

■位置情報が入力された場合の「event」の一部

青下線の「type」がlocationに変わり、
緑下線の「latitude」「longitude」に緯度経度の情報が格納されています。

そのため、青下線の「type」がtextだった場合は、
これまで通り、LINEで入力された文字列をfrom_textに代入し、
入力内容に沿ってto_textを定義する処理を実行し、
そうでない場合(青下線の「type」がlocation)の場合、
「latitude」「longitude」から緯度経度を取得するよう、処理を分岐してください

■「type」の判別

json.loads(event['body'])['events'][0]['message']['type'] == 'text'

■緯度経度取得処理

latitude  = json.loads(event['body'])['events'][0]['message']['latitude']
longitude = json.loads(event['body'])['events'][0]['message']['longitude']

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

hotpepper_functionのshop_search関数の引数は、「from_text」一つだけのため、
①で追加した分岐内で、「latitude」「longitude」の
2つの引数を引数とするshop_search_map関数を呼び出し、
結果を「to_text」に代入してください


・「hotpepper_function.py」への修正

hotpepper_function.py内に、「latitude」「longitude」を
引数とするshop_search_map関数を追加してください。

これまでのshop_search関数は、引数「keyword」をHotpepperAPIへの
リクエストパラメータ「hp_param」に定義し、
キーワードでおすすめ店舗を検索していました。

追加するshop_search_map関数では、緯度経度でおすすめ店舗の検索を行うため、
引数「keyword」ではなく、「latitude」「longitude」を
「hp_param」に定義し、HotpepperAPIにリクエストを送信し、
レスポンスを「to_text」に代入し、lambda_functionに返してください。

■緯度経度検索用パラメータ定義

# HotpepperAPIへのリクエストパラメータ準備
hp_pram = {
    'key':HP_API_KEY,
    'lat':latitude,
    'lng':longitude,
    'order':4,
    'count':1,
    'format':'json'
}

改行コードで区切る処理や、要素数を確認する処理は不要です。
また、HotpepperAPIにリスエストを送信し、
レスポンスから情報を取得する処理は、そのまま利用して問題ございません。


・LINEでの位置情報の送信方法

位置情報は、以下のリンクを参考に、送信してください。
PC版のLINEでは送信できないため、携帯から送信してください。

▼位置情報 送信方法
https://guide.line.me/ja/services/location-information.html

デフォルトでは、現在地にピンが立っているため、
任意の場所にピンの位置を変更してください