###### tags: `Python勉強会`
# 【50期】Python勉強会 第8回
:::info
**<第8回Web会議日程>**
2023年06月21日(水)19:00から
:::
## 第7回 解説
### ・課題
**現在、「<span style="color:blue">lambda_function.py</span>」は、以下のようにLINEで入力した場合、**
**2行目をキー、3行目を値としたJSONファイルをS3に書き込みます。**

**上記に以下のようにLINEで入力した場合、S3のJSONファイルを読み込み、**
**キーに対応する値をに応答する処理を追加してください**

### ・回答例
```python=
def s3_output(from_text):
# 入力内容を改行コードで区切ってリスト型に格納
str = from_text.split('\n')
# リストの要素数が1つより大きいの場合
if( len(str) > 1 ):
# リストの2要素目(キー)がjson_dataに含まれる場合
if( str[1] in json_data ):
# キーに対応する値を「to_text」に格納
to_text = json_data[str[1]]
# リストの2要素目(キー)がjson_dataに含まれない場合
else:
to_text = str[1] + 'は登録されていません'
else:
to_text = '2行目にキーを入力してください'
return to_text
```
### ・解説
「s3_output」関数実行時には、
「s3_function.py」内のjsonファイル読み込み処理実行済みのため、
変数「json_data」は以下となる
```python
# json_data
{'明日の予定': '仕事'}
```
「from_text」には、LINEでの入力内容が以下の文字列として入る
```python
# from_text
'出力\n明日の予定'
```
このままでは処理できないため、「from_text」を改行コードで区切ってリスト型「str」に格納する
```python!
str = from_text.split('\n')
```
「str」は以下のようなリストの値となる
```python!
# str
['出力', '明日の予定']
```
リスト型「str」の2つ目の要素の値をキーとして、
辞書型「json_data」から値を取り出し、「to_text」に代入できていれば、OK
```python
to_text = json_data[str[1]]
```
上記に加え、想定外の入力があった場合の処理として、以下を追加
・「出力」から始まる1行しか入力がなかった場合、「2行目にキーを入力してください」を返す
・2行目にs3のjsonにないキーが指定された場合、「 キー は登録されていません」を返す
------
## 第8回 課題
### ・課題の前に。。。
各自第7回で対応したLambdaに以下の修正を追加してください。
・「NewFile」をクリック

・展開した「hotpepper_function.py」を反映し、「Save As...」をクリック

・FileNameに「hotpepper_function.py」と入力し、「Save」をクリック

・「<span style="color:blue">lambda_function.py</span>」で「hotpepper_function」をインポート
```python
import hotpepper_function
```
・requestsモジュールを利用するためのレイヤーを関数に追加
※対応済み
・HotpepperAPIを利用するためのAPIキーを環境変数に追加
※対応済み
----
### ・課題
**現在、「<span style="color:blue">lambda_function.py</span>」は、以下のようにLINEで入力した場合、**
**何も処理されません**

**上記に以下のようにLINEで入力した場合、2行目を検索キーワードとして、**
**HotpepperのグルメサーチAPIにリクエストを送信し、**
**おすすめのお店を一軒紹介するよう処理を追加してください**

-----
### ・課題の概要
今回からの課題では、**HotpepperAPI**という無料で公開されているAPIを利用します。
このAPIは、公開されているURLにリクエストを送信すると、
キーワードに応じて店舗を検索し、その情報を返してくれます。
今回の課題では、LINEの入力内容をキーワードにこのAPIにリクエストを送信し、
APIから返された情報から**掲載店名**を抽出し、LINEに返すように関数を修正いただきます。
**※要修正**
ーーーーーーーーーーーーーーー
「公開されているURLにリクエストを送信する」部分は、
上記で追加した「hotpepper_function.py」に定義済みのため、
以下の修正をお願いいたします。
・「lambda_function.py」から「hotpepper_function.py」のshop_search関数を呼び出す
・APIから返された情報から、**掲載店名**を取り出し、LINEに返す
ーーーーーーーーーーーーーーー
-----
### ・前回からの変更点

①個人のスマホからLine公式アカウントにメッセージ送信
②Line公式からWebhookしたAPI GatewayのURLへメッセージを送信
③API Gatewayに関連付けられたLambdaを呼び出し
<span style="color:red">④HotpepperAPIにリクエスト</span>
⑤Lambdaで作り込んだ処理に沿ってメッセージを応答
-----
### ・「<span style="color:blue">hotpepper_function.py</span>」概要
#### 1 . HotpepperAPIにリクエストを送信
入力内容(from_text)を改行コードで区切って変数「str」にリスト型で格納
```python
['ホットペッパー', '池袋']
```
変数「hp_pram」に、リクエストに必要な検索条件を定義し、
HotpepperAPIのURLにGETリクエストを送信
```python
# HotpepperAPIへのリクエストパラメータ準備
hp_pram = {
'key':HP_API_KEY,
'keyword':keyword,
'order':4,
'count':1,
'format':'json'
}
```
:::success
今回のリクエストでは、以下のパラメータを利用
詳細やその他のパラメータは[APIリファレンス](https://webservice.recruit.co.jp/doc/hotpepper/reference.html)を参照
**・key**:
APIを利用するためのキー
**・keyword**:
フリーワード検索のためのキーワード
LINEでの入力内容でお店を検索する
**・order**:
検索結果の並び順を指定できる
「4」はおすすめ順
**・count**:
検索結果のデータ数を指定できる
「1」を指定しているため、1店舗だけの情報が返る
**・format**:
レスポンスの形式を指定できる
Pythonで処理するため、「JSON」を指定
:::
#### 2 . レスポンスからお店の情報を取得
お店の情報が格納されたJSON形式のレスポンスを辞書型「response_dict」に変換
必要情報を抽出し、LINEへの返答内容(to_text)を定義
※「response_dict」は見やすいよう整形した状態でログに出力しています
```python
logger.info(json.dumps(response_dict,indent=2,ensure_ascii=False))
```
-----
### ・ホットペッパーAPI
:::info
**<ホットペッパーAPIとは>**
【URL】ホットペッパーAPI
https://webservice.recruit.co.jp/doc/hotpepper/reference.html
リクルートが提供してくれている無料のAPIサービス。
※今回はグルメサーチAPIを利用
ホットペッパーAPIを利用するには利用申請が必要となる。
[リンク](https://webservice.recruit.co.jp/register/)より新規登録し、APIキーを取得する必要がある。
※今回は講師側で取得し、環境変数に登録済み。
**<使い方>**
#### ①APIに対し、リクエストを送信する
・以下のURLに対してリクエストを送信する
http://webservice.recruit.co.jp/hotpepper/gourmet/v1/
・送信時に検索クエリをリクエストパラメータとして送信できる
・検索クエリの条件に一致するお店をホットペッパー内で検索してくれる
・どのような検索クエリを指定可能か、は
[リファレンス](https://webservice.recruit.co.jp/doc/hotpepper/reference.html)のグルメサーチAPI、検索クエリを参照
### ②レスポンスを受け取る
・検索クエリに指定した条件に一致する店舗の情報がレスポンスとして返される
・データの形式はリクエスト時に指定でき、
JSONを選択すると、Pythonで辞書型に変換可能
・レスポンスにどのような情報が含まれるか、は
[リファレンス](https://webservice.recruit.co.jp/doc/hotpepper/reference.html)のグルメサーチAPI、レスポンスフィールドを参照
:::
-----
### ・Lambda レイヤー
:::warning
・Lambdaレイヤーは、追加のコードまたはデータを含むことができる .zipファイルをまとめたもの。ライブラリ、カスタムランタイム、データ、または設定ファイルを含めることができる。
・lambdaでサードパーティライブラリを使うにはLayerを使う必要があり、AWS Lambda上でもサードパーティー製のライブラリを使うことができる。
・Lambdaは標準ライブラリしか使えず、外部モジュールを使用するにはインストールしなければならない。
また、ファイルをAWSにアップロードすると、関数で利用できる
:::
#### ※今回は講師側でrequestsのレイヤーを登録済みです!!
-----
### ・requestsについて
:::warning
**<requestsとは>**
HTTP通信用のPythonのライブラリ
GET、POST、PUTなどのメソッドが用意されている
今回は、HTTPでHotpepperAPIにGETリクエストを送るために使用
外部モジュールのため、利用するにはインストールの必要がある
今回はLambdaのため、Layerとして追加
```
pip install requests
```
<br>
**<GETメソッド>**
**`requests.get(リクエスト送信先URL,リクエストパラメータ)`**
URLに対してGETリクエストを送ることができる
リスエストの結果が、Responseオブジェクトとして返される
:::
-----
### ・辞書型を見やすく表示する方法について
:::warning
**<json.dumps>**
・PythonオブジェクトをJSONデータに変換するための関数
・変換時にindentパラメータを設定すると、
print()や、loggerで表示した時に見やすくなる
・日本語が含まれる場合は、「ensure_ascii = False」を引数に指定する
```python
logger.info(json.dumps(response_json,indent=2,ensure_ascii=False))
```
:::
---
### ・ローカルで実行するためのコード
Lambda上で試行錯誤することが煩わしい場合、
ローカルで「hotpepper_function.py」と同様のAPI利用結果を
取得できるコードを準備してしましたので、ご利用ください
```python=
import requests
import json
HP_URL = 'http://webservice.recruit.co.jp/hotpepper/gourmet/v1/'
HP_API_KEY = '003698bcd54c9063'
keyword = '池袋'
# HotpepperAPIへのリクエストパラメータ準備
hp_pram = {
'key':HP_API_KEY,
'keyword':keyword,
'order':4,
'count':1,
'format':'json'
}
# HotpepperAPIにリスクエスト
response = requests.get(HP_URL,hp_pram)
# レスポンスを辞書型に変換
response_dict = response.json()
print(json.dumps(response_dict,indent=2,ensure_ascii=False))
```
「ModuleNotFoundError」が出る場合は、requestsとjsonを
コマンドプロンプトでpip install してください