AWSでゴミ分別APIを作った

AWSでゴミ分別APIを作った:


はじめに

AWS環境にゴミ分別をしてくれるAPIを作ります。

Cloud9を使用します。試してみた記事は以下です。

Cloud9でPythonを試してみる - Qiita


設計

分別したいゴミをパラメータで渡すと結果を返すAPIを作ります。

ごみの分別ですが、川崎市のゴミ分別のデータセットがCCライセンスで公開されているのでそれを使用します。

川崎市:オープンデータ化に向けた取組

データセットは更新されることがありそうです。

このことから、APIは以下のようにバージョンも指定できるようにします。

GET /garbage?word=皿&v=300110 


開発


lambda関数を作成する

cloud9からAPI Gatewayと連携したLambdaを作成します。

[AWS Resources]からLambdaの追加アイコンを選択。



image


名前は適当。



image


テンプレートはAPI Gatewayを使っているものを選んでみました。



image


エンドポイントのパスも適当に。セキュリティは後々考えます。



image


開発なのでメモリは最低。Roleは自動生成します。



image


Finish!



image


できました。



image



Lambda関数を実装する

テンプレートとして利用したものはDynamoDBを使用していますが、ここではそこまでする必要はないので、インスタンス単位でCSVファイルを読み込むこととします。

あとは読み込んだファイルの内容からマッピングを返すだけなので、説明することはありません。

注意点はコピーしてきた公開されているCSVファイルがShift-JISである点くらいです。

lambda_function.py
# -*- coding: utf-8 -*- 
import csv 
import json 
import os 
import logging 
 
logger = logging.getLogger(__name__) 
logging.basicConfig(level=logging.DEBUG) 
 
_cache = None 
 
 
class AppError(Exception): 
    """ 
    汎用エラークラス 
    """ 
    def __init__(self, message): 
        self.message = message 
 
 
def lambda_handler(event, _): 
    """ 
    lambda 
 
    :param event: 
    :param _: context 
    :return: 
    """ 
    print("Received event: " + str(event)) 
 
    version = event.get('queryStringParameters', {}).get('v', None) 
    word = event.get('queryStringParameters', {}).get('word', None) 
 
    # 入力チェック 
    if not version or not word: 
        return respond(None, err=AppError('invalid parameter')) 
 
    # データベースの取得 
    if not _update_cache(version): 
        return respond(None, err=AppError('Unsupported version "{}"'.format(version))) 
 
    result = _cache.get(version, {}).get(word, '分類できませんでした') 
    return respond({ 
        'version': version, 
        'classification': result, 
    }) 
 
 
def _update_cache(version): 
    """ 
    データベースを更新する 
 
    :param version: 
    :return: 
    """ 
    global _cache 
 
    if not _cache: 
        _cache = {} 
 
    if version not in _cache: 
        _cache[version] = {} 
        filename = './' + version + '.csv' 
        if os.path.exists(filename): 
            with open(filename, 'r', encoding='shift_jis') as f: 
                reader = csv.reader(f) 
                next(reader) 
                # 0 ,1     ,2     ,3   ,4     ,5             ,6             ,7               ,8 
                # ID,頭文字,品目名,読み,類似語,出し方(一覧),出し方(詳細),出し方のポイント,URL1 
                for row in reader: 
                    out = row[5] 
                    if row[6].strip(): 
                        out += 'または' + row[6] 
                    _cache[version][row[2]] = out 
                    _cache[version][row[3]] = out 
                    if row[4].strip(): 
                        synonyms = row[4].split(' ') 
                        for synonym in synonyms: 
                            _cache[version][synonym] = out 
                return True 
        else: 
            logger.warning('file not exist.') 
            return False 
    else: 
        # すでに取得済み 
        return True 
 
 
def respond(res, err=None): 
    """ 
    API Response 
 
    :param err: 
    :param res: 
    :return: 
    """ 
    return { 
        'statusCode': '400' if err else '200', 
        'body': err.message if err else json.dumps(res, ensure_ascii=False, indent=2), 
        'headers': { 
            'Content-Type': 'application/json', 
        }, 
    } 


サーバーレスの設定

デプロイ時の設定はtemplate.yamlで行います。テンプレートで作成済みです。

ここではMemorySizeを小さく、受け取るMethodをGETのみにする、といった変更を行いました。

template.yaml
AWSTemplateFormatVersion: '2010-09-09' 
Transform: 'AWS::Serverless-2016-10-31' 
Description: An AWS Serverless Specification template describing your function. 
Resources: 
  garbage: 
    Type: 'AWS::Serverless::Function' 
    Properties: 
      Handler: garbage/lambda_function.lambda_handler 
      Runtime: python3.6 
      Description: '' 
      MemorySize: 128 
      Timeout: 15 
      CodeUri: .debug/ 
      Events: 
        LambdaMicroservice: 
          Type: Api 
          Properties: 
            Path: /garbage 
            Method: GET 
  garbagePermission: 
    Type: 'AWS::Lambda::Permission' 
    Properties: 
      Action: 'lambda:InvokeFunction' 
      FunctionName: 
        'Fn::GetAtt': 
          - garbage 
          - Arn 
      Principal: apigateway.amazonaws.com 
      SourceArn: 
        'Fn::Sub': 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*/*/*/*' 


デプロイ

IDEのLambdaメニューからデプロイします。



image



確認

AWSのAPI GatewayからURLを確認して実行してみます。



image


https://****************.us-west-2.amazonaws.com/Stage/garbage?word=パソコンケース&v=300110 
ブラウザなどから取得したURLを入力して以下のようなレスポンスが返ってくればOKです。

{ 
  "version": "300110", 
  "classification": "普通ごみまたは粗大ごみ" 
} 


おわりに

このAPIを使用した企みは別の記事で行います。


参考

AWS Cloud9 Integrated Development Environment (IDE) で AWS Lambda 関数を操作する - AWS Cloud9

Python3 で CSV の読み書きをする方法 – Shift_JIS と UTF-8 対応サンプルコード付 | Crane & to.

19.2. json — JSON エンコーダおよびデコーダ — Python 3.6.5 ドキュメント

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)