世界で一番簡単に痩せられるLine Bot

#はじめに
このラインボットはスクールの製作物発表会のために、プログラミングを始めて３ヶ月後に製作開始したものです。
もし学習を開始して何を作るか悩んでいる人がいたら参考になれば幸いです。
また初めて作った製作物のためコードが荒い部分が少し多いです。これこうしたら？って部分があればコメントでそっと教えてもらえるとありがたいです。
#なぜ作ったのか
僕は常々太ることに対して、痩せることが難しすぎることに不満を抱いていました。
**ダイエットは理想的な運動をして、毎食カロリーを計算したご飯を摂取するのを３ヶ月、少なくとも１ヶ月は継続しないと成功しません。**しかしながらそれを成し遂げるにはマーラのごとき誘惑を跳ね除けねばなりません。仕事終わりの堪え難い休息欲。もはや慢性的ともいえるラーメン欲と飲酒欲。運動不足ゆえの運動への忌避感。
現代人の戦いはいつも困難です。
そこで**食べて太ったなら、食べるだけで痩せられる！**そんな楽チンなサービスを考えて出来たのがこのラインボットです。
#どうして痩せるのか
ところで1キロ痩せるには何キロkcal燃焼させる必要があるかご存知でしょうか？
**実はこれ７０００キロkcalと言われているんです。**
このラインボットでは入力してもらった身長、体重、年齢、性別を基に基礎代謝を割り出し、それより１０００kcal少ない目標摂取kcalを計算し、LAWSONとセブンイレブンの商品からランダムで献立を作成し、ラインで送信してくれるというものです。
**つまりあなたはラインで受信した献立の商品を購入して食すだけで、一週間につき7000kcal削減でき、１キロ減量できます。月ごとだと４キロのダイエット成功です！！
あなたのすることは言われた通りに食べるだけ！！！**
#ターゲット
運動せずに痩せたい人(特に運動が苦手な女性とか)
今の体型を維持したい人(パーティーや飲み会の前日と後日にオススメ！)
一人暮らしで毎日何食べるか考えるのが面倒になってきた人
#友達登録
このラインボットを試してみたい方は以下からLINEで友達追加してください。
![646hrric.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578416/f1630c6a-5711-d20d-130c-0a94b26dd304.png)
#使い方
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578416/0b681596-8685-e688-bf75-4ff3cdc4ac03.jpeg"width=70%>
１、まず友達追加したら”設定”と送信してメッセージを受け取ってください
２、送られてきたフォーマットに沿ってパーソナルデータの設定を完了してください（入力例：**登録。178-78-25-1**）
３、以後は”ローソン”か”セブン”と送信すれば献立が受け取れます
#実装した機能
１、ウェブページをスクレイピングした結果をリストにまとめてファイル保存
２、ユーザーから受けとったパーソナルデータから朝、昼と夜に摂取すべきkcalを計算し、獲得したユーザーidと一緒にデータベースに保存
３、ユーザーから献立のリクエストを受信したら、データベースから該当ユーザーのデータを呼び出す。
４、コンビニ商品リストからランダムで商品を抜き出し、目標kcalに近くなるまでループ。結果をユーザーに送信
#コードについて
スクレイピングのコードとメインコードのみ記載します。
全文で見たい方は僕のgit hubからどうぞ。
[git hub](https://github.com/moto1994/diet-bot)
#スクレイピングのコード
ローソンの方も載せると長いのでセブンのだけ記載。

```python:mk-data.py
import requests
from bs4 import BeautifulSoup as bs
import pickle
```
BeautifulSoupでスクレイピング、pickleを使ってファイルに保存します。

```python:mk-data.py
#セブンのスクレイピング関数
def seven_scraping(url):
    header = {"User-Agent" : "Mozilla/5.0"}
    s = bs(requests.get(url, headers=header).content, 'html.parser')
    
    #名前
    s_names = []
    for i in s.find_all('div', class_='itemName'):
        s_names.append(i.text)

    #画像        
    s_images = []
    for i in s.find_all('div', class_='image'):
        j = i.a.get("href")
        s_images.append("https://www.sej.co.jp"+j)

    #カロリー
    s_kcals = []
    for i in s.find_all('div', class_='summary'):
        j = i.find('li', class_ ='n1')
        j = j.text
        j = j.strip("※地域によりカロリーが異なる場合があります。")
        j = j.split("kcal")[0]
        j = int(j)
        s_kcals.append(j)

    return list(zip(s_kcals, s_names, s_images))
```
スクレイピングしたデータを名前、画像、カロリーのリストとして作成し。最終的にそれらを一つのリストに結合させて返す関数。

```python:mk-data.py
def main():
    seven_url ="https://www.sej.co.jp/i/products/anshin/calorie/"
    seven_list = seven_scraping(seven_url)
    f = open('seven_list.txt', 'wb')
    list_row02 = seven_list
    pickle.dump(list_row02, f)

if __name__ == '__main__':
    main()
```
関数を実行しpickleを使ってファイルに保存
#メインコード
```python:main.py
from flask import Flask, request, abort
import os
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

import re
import pickle
import random
import sqlite3
```

```python:main.py
app = Flask(__name__)
LINE_CHANNEL_ACCESS_TOKEN = os.environ["LINE_CHANNEL_ACCESS_TOKEN"]
LINE_CHANNEL_SECRET = os.environ["LINE_CHANNEL_SECRET"]
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)
f = open("./lawson_list.txt","rb")
list_row = pickle.load(f)
f02 = open("./seven_list.txt","rb")
list_row02 = pickle.load(f02)
```
さっき保存した商品データを呼び出したりする。

```python:main.py
#基礎代謝を計算する関数し、目標値を返す
def base_energy(tall, weight, age, sex):
    if sex == 1:
        result = 13.397 * weight + 4.799 * tall - 5.677 * age + 88.362
        return result
    else:
        result = 9.247 * weight + 3.098 * tall - 4.33 * age + 447.593
    
    result = (result * 1.75) -1000
    return round(result)
```
ハリス・ベネディクト方程式(改良版)を使って基礎代謝量を計算しています。
男性： 13.397×体重kg＋4.799×身長cm−5.677×年齢+88.362
女性： 9.247×体重kg＋3.098×身長cm−4.33×年齢+447.593
参考："https://keisan.casio.jp/exec/system/1161228736"

```python:main.py
#朝と昼・夜のカロリーを計算
def create_before(aim_kcal):
    return int(aim_kcal * 0.2)
def create_after(aim_kcal):    
    return int(aim_kcal * 0.4)

#メニューをランダムに選ぶ関数
def make_menu(aim_num, conv_list):
    menu = []
    x = 0
    #目標カロリーのプラマイ100kcalになるまでループ
    for i in range(150):
        i = random.choice(conv_list)
        if aim_num -100 <= x <= aim_num + 100:
            return menu
            break
        if i[0] + x <= aim_num + 100:
            x += i[0]
            menu.append(i)
        else:
            continue 
```
1日の目標kcalを朝：昼：夜で2：4：4の比率にする。
メニューの作成関数は目標値に近くなるまで、ランダムで商品リストから呼び出し続けるパワープレー。
↓少し中略

```python:main.py
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    word = event.message.text
    if word in ["ローソン"]:
        #朝と昼・夜の基礎代謝データを呼び出し
        profile = line_bot_api.get_profile(event.source.user_id)
        user_id = profile.user_id
        conn = sqlite3.connect('database.sqlite3')
        c = conn.cursor()
        c.execute('SELECT * FROM user WHERE id=?', (user_id,))
        list1 = c.fetchone()
        before_noon = list1[1]
        after_noon = list1[2]
        conn.commit()
        conn.close()
        today_morning = make_menu(before_noon, list_row)
        today_lunch = make_menu(after_noon, list_row)
        today_dinner= make_menu(after_noon, list_row)
        today_menu = []
        for i in today_morning:
            today_menu .append( "\n朝ご飯は" + str(i))
        for i in today_lunch:
            today_menu.append("\n昼ご飯は" + str(i))
        for i in today_dinner:
            today_menu.append("\n夜ご飯は" + str(i))
        reply = ','.join(today_menu)

        line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=reply))
```
献立のリクエストを受けたらuser_idを獲得し、該当ユーザーの目標カロリーを呼び出し。
その数値と商品リストから作成した献立をユーザーに送信。

```python:main.py
    elif word in ["設定"]:
        setup_text = """以下のフォーマットで入力してください\
        
        登録。身長-体重-年齢-性別（１男性　or　2女性）
        ＊全て半角数字をご使用してください
        ＊例　　　　登録。168-68-24-1
        """
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=setup_text))

    elif 0 <= word.find('登録。') :
        #受けとったデータを身長、体重、年齢、性別に分ける
        #それをbase_energyに渡す
        personal_data = event.message.text
        personal_data = personal_data.replace("登録。", "")
        personal_data = personal_data.replace("-", ",")
        personal_data = personal_data.split(',')
        tall = int(personal_data[0])
        weight = int(personal_data[1])
        age = int(personal_data[2])
        sex = int(personal_data[3])
        aim_kcal = base_energy(tall, weight, age, sex)
        #各食ごとのカロリーを算出
        #データベースに書き込み
        profile = line_bot_api.get_profile(event.source.user_id)
        prof_dict = {}
        prof_dict["id"] = profile.user_id
        prof_dict["before_noon"] = create_before(aim_kcal)
        prof_dict["after_noon"] = create_after(aim_kcal)
        conn = sqlite3.connect('database.sqlite3')
        c = conn.cursor()
        c.execute('insert into user(id, before_noon, after_noon) values(:id, :before_noon, :after_noon);', prof_dict)
        conn.commit()
        conn.close()

        line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text="設定は完了したよ"))

    else:
        line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text="ローソンかセブンか設定と入力してください"))

if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)
    app.run()
```
ユーザーからフォーマット通り送られたデータを処理し、目標値を出し、朝昼晩に分割。

```
$ heroku login
heroku create <アプリケーション名>
```

herokuにアプリケーションを登録して


```
$ git init
$ git add .
$ git commit -m "new commit"
$ git push heroku master
```
pushして終わり。

#使用感
完成後一週間自分で使って見ました。感想としては
＜＜メリット＞＞
１、意外とサラダが多くて健康的（ランダムで商品を呼び出すループにより低カロリーなサラダが選ばれやすい）
２、普段買わないものを食すので感動する商品に出会うことがある
３、意外と満腹感はある
４、**1キロ痩せた！！**
![IMG_20200202_112624.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578416/a99c6fb8-5d45-1eef-9333-4b03d46edf15.jpeg)
ある日の夕飯（意外とボリューミー）

＜＜デメリット＞＞
１、節約には向いてない（1日1500~2000円はかかる）
２、品切れが多い
３、継続的使用は飽きる（無理せず使うくらいでも一応効果はある）
#収益案（大手コンビニが類似サービスを導入したとしたら）
##１、広告効果
**1日の購買費が1500円以上はかかるため、アクティブユーザーが１人で１月あたり約45000円以上の売り上げ増加が見込める。１００人なら４５０万円以上期待できる。**
また広告効果が他の媒体に比べて、直接購買行動に結びつくまでが早い。例えばテレビcmで新商品を知った時、私たちは実際にそれを購入するまでいくらかのタイムラグが生まれる。実際に広告をみてすぐさま購入する場面は稀であり、潜在意識に広告効果が働き、時間がたってから購買行動に繋がる。その場合、無意識に顧客行動に影響を与えたわけであるから広告効果を測るには売り上げの増減から推測するしかなくなってしまう。それに対して、このサービスではユーザーは献立を受け取ったその日に購買に結びつく期待が高く、またLineディベロッパーからいまどの程度のアクティブユーザーがいるか判断することが容易である。かつ費用自体も一番高いもので月30000円程度と他媒体に比べて安価だ。
**つまり広告効果、即効性、把握力が高く、また低コストに実装できる。**
##２、レビュー機能とクーポンとの相性がいい
『また食べたいかどうか』を答えてもらうと、翌日限定の割引クーポンを発行する機能をつければユーザーのリピート率の上昇と顧客の商品評価の獲得が期待できる。
ユーザー視点から見ると、『痩せられる』メリットだけでなく、翌日『安く購入できる』メリットを獲得でき、このサービスのウィークポイントである『節約に向いてない』という点をいくらかカバーできるし、ユーザーのダイエット継続の一助にもなる。企業側から見ても、継続率が上がれば売り上げもまた上がるし、献立がランダムのため幅広い商品のデータを獲得できるというメリットも大きい。
##３、ビッグデータとしての有用性
コンビニのポイントカードではどんな性別、年代の人が商品を購入したかというデータしか集まらない。言い換えれば購入するまでのデータでしかない。しかし、本来商売は購入したという時点で終わるものではない。私たちは『この商品が自分のニーズを満たしてくれる』と考えて購買し、使用して所感を抱き、リピートするか判断を下す。継続的に顧客を獲得する仕組みを作るには、購買した後のデータを収集することは重要だ。**購買層のデータと顧客層ごとの商品評価データ。**２つのデータを組み合わせるメリットはとても大きい。
##４、活用例
先ほどの２つのデータから商品を4つのグループに分ける。
①売り上げが<font color="OrangeRed">高く、</font>評価も<font color="OrangeRed">高い</font>商品
②売り上げが<font color="OrangeRed">高く、</font>評価が<font color="Blue">低い</font>商品
③売り上げは<font color="Blue">低く、</font>評価は<font color="OrangeRed">高い</font>商品
④売り上げが<font color="Blue">低く、</font>評価も<font color="Blue">低い</font>商品

![無題のプレゼンテーション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578416/00560dcb-e614-5191-7694-2fb5eeb39a2d.jpeg)

上記のグループに分けることで、商品開発戦略と流通管理の面で大きな恩恵を受けられる。
まず流通管理の面では①の商品は今後も高い売り上げが見込めるが、④に関しては顧客が購入する可能性が低く、もし購入されてもリピートが期待できない。**④を早めに生産中止にし、①の生産を増やすことで店舗での廃棄を減らし営業利益の向上が見込める。**
次に商品開発の面に関しては②と③を分析することで大きなメリットが受け取れる。②は有害である。なぜなら多くの顧客の期待を裏切ってしまう商品だからである。多くの人が魅力を感じて購入するが、家に帰って食べてからがっかりさせてしまう。しかし、**②は買うまではとても魅力的な商品**であることは間違いなく、顧客の手に取らせる何かがある商品なのだ。**つまり商品のマーケティング自体はうまくいっている可能性は高い。**③は今は売れていないが、時間とともにジワジワと売れ始めたり、デザインやネーミングを変更することで売れる可能性がある。②の分析を活用すれば大きく売り上げを伸ばす可能性がある。
##５、事業拡大
コンビニは最も日本人の購買と嗜好のデータを収集できる可能性があるビジネスだ。また自社商品のみでなく他社の商品（大手お菓子会社や食品会社など）を扱うため、ビッグデータとその分析をそれらの会社に売却すれば今以上の収益をあげられるのではないだろうか。またデータ分析で培ったノウハウを活かして、地方の会社のご当地商品をプロデュースしてみてもおもしろそうだと思う。