ランダムおすすめ記事

ホームページ作りました

(いちばんやさしいpython教本の改造)観客動員予測システム「ベルマーレ観客動員予測1号ちゃん」プログラム解説①

作りました。

ベルマーレ観客動員予測1号ちゃん

作ったのでアウトプットもかねてプログラム解説をつけようと思います。
素人なので解説なんて大げさなものじゃありませんね。ただ理解を深めたり復習するにはアウトプットがいいんですよね。

分析手法についてはこちらを見てください。

重回帰分析を使ってベルマーレの観客動員数を予測したい!!!① - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定

重回帰分析を使ってベルマーレの観客動員数を予測したい!!!② - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定

コードはこちら

GitHub - sr2460/douinyosoku-1

考えたこと

まずdjangoでしかwebアプリケーションを制作したことが無かったので簡単なアプリをbottleで作ろうと思いました。
ただしさくらvpsを使う場合すでにdjangoのアプリケーションがデプロイされているので最終的にdjangoに書き換える必要はあるかもしれないと考えました。
一番やさしいpython教本をもとに改造を加えるのでとりあえずbottleで作った証としてherokuにアップロードする可能性は考慮していました。(本の内容をherokuにbottleでデプロイしたことがある)


元のプログラムの解説

プログラム的にやったことでまとめていきたいことを書いていきます。
このアプリは「いちばんやさしいpython教本」を基に改造をしてあります。


まずはもとのアプリを少し解説してみましょうか。
以下がpybotweb.py

import os 
from bottle import route, run, template, request
from pybot import pybot


@route('/hello')
def hello():
    return template('pybot_template', input_text='', output_text='')


@route('/hello', method='POST')
def do_hello():
    input_text = request.forms.input_text
    output_text = pybot(input_text)
    return template('pybot_template', input_text=input_text, output_text=output_text)


#run(host='localhost', port=8080, debug=True)
run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000))) 

普通にURL+/helloのページに遷移した場合

input_text='', output_text=''



部分は空欄になっていることが分かります。

以下html部分(template.tpl)↓

<html>
<body>
<h1>pybot Webアプリケーション</h1>
<form method="post" action="/hello">
メッセージを入力してください: <input type="text" name="input_text">
<input type="submit" value="送信">
</form>
<ul>
<li>入力されたメッセージ: {{input_text}}</li>
<li>pybotからの応答メッセージ: {{output_text}}</li>
</ul>
</body>
</html>

formにメッセージを入れるとフォームでの送信はPOST

<form method="post" action="/hello">

となるので

@route('/hello', method='POST')

以下がURLに出力されます。

html部分を見てみると、inputテキストに出力がされるようになっていますね。

↓以下に出力

<li>入力されたメッセージ: {{input_text}}</li>
<li>pybotからの応答メッセージ: {{output_text}}</li>



ここで関数を見てみると

    input_text = request.forms.input_text
    output_text = pybot(input_text)
    return template('pybot_template', input_text=input_text, output_text=output_text)



input_textはそのままフォームで送信されたinput_textが出力されますがoutput_textは

output_text = pybot(input_text)

が出力されることになります。

output_text = pybot(input_text)とは何かというとpybot.pyというファイルに

command_file = open('pybot.txt', encoding='utf-8')
raw_data = command_file.read()
command_file.close()
lines = raw_data.splitlines()

bot_dict = {}
for line in lines:
    word_list = line.split(',')
    key = word_list[0]
    response = word_list[1]
    bot_dict[key] = response

def pybot(command):
    # command = input('pybot> ')
    response = ''
    try:
        for key in bot_dict:
            if key in command:
                response = bot_dict[key]
                break

            if '平成' in command:
                response = heisei_command(command)
            if '長さ' in command:
                response = len_command(command)
            if '干支' in command:
                response = eto_command(command)
            if '選ぶ' in command:
                response = choice_command(command)
            if 'さいころ' in command:
                response = dice_command()
            if '今日' in command:
                response = today_command()
            if '現在' in command:
                response = now_command()
            if '曜日' in command:
                response = weekday_command(command)
            if '天気' in command:
                response = weather_command()
            if '事典' in command:
                response = wikipedia_command(command)

        if not response:
            response = '何ヲ言ッテルカ、ワカラナイ'
        return response



こんなコードがあるのですがここの

def pybot(command):


以下となります。

 if '平成' in command:

もしコマンドの中に平成があれば

                response =            if '平成' in command:
                    response = heisei_command(command)

レスポンスに関数heisei_command(command)が代入されます。
これは平成 西暦の年数のようにフォームに入力すると平成○年は西暦○年ですよと教えてくれるプログラムです。

def heisei_command(command):関数は以下のようになっており、

def heisei_command(command):
    heisei, year_str = command.split()
    if year_str.isdigit():
        year = int(year_str)
        if year >= 1989:
            heisei_year = year - 1988
            response = '西暦{}年ハ、平成{}年デス'.format(year, heisei_year)
        else:
            response = '西暦{}年ハ、平成デハアリマセン'.format(year)
    else:
        response = '数値ヲ指定シテクダサイ'
    return response



heisei, year_str = command.split()

と書いてあるようにsplit()で空欄で文字を分割。heisei変数とyear変数に分割します。

returnはresponse。

            response = '西暦{}年ハ、平成{}年デス'.format(year, heisei_year)
        else:
            response = '西暦{}年ハ、平成デハアリマセン'.format(year)
    else:
        response = '数値ヲ指定シテクダサイ'
    return response



def pybot(command):
            (中略)
            if '平成' in command:
                response = heisei_command(command)


と書かれているのでたった平成 1989のように打ち込むとheisei_command(command)がresponseに代入され

関数でpybot(input_text)が処理した戻り値がoutput_textに代入され

@route('/hello', method='POST')

    output_text = pybot(input_text)
    return template('pybot_template', input_text=input_text, output_text=output_text)



html部分の

<li>pybotからの応答メッセージ: {{output_text}}</li>


に出力されます。これが基本的な機能になります。
このプログラムを基に改造をし、「ベルマーレ観客動員予測1号ちゃん」を完成させました。


プログラム的に改造したところで特に書きたいこと

ここから改造した部分で特に書きたいことを書いていきます。
まずただのフォームでは味気ないと思ったのでLINE風のフォームに変更しました。
このページを丸写し参考にしました。
CSSで作る!吹き出しデザインのサンプル19選

ただしフォーム部分と上の名前のところは自分で考えて改造しました。 f:id:sr2460:20190313113246p:plain

フォーム部分はcssは以下のようになっています。

.line-top {
  max-width: 100%;
  text-align: center;
  font-size: 16px;
  background: #003a66;
  /*paddingで幅を広げようと思ったらなぜか無理だった */
  border: solid 10px #003a66
}

.line-top strong {
color: #FFFFFF;

}


文字の部分は画像と文字の上下幅がぎりぎりだったので広げようと思いpaddingを改造していたのですがなぜか全く動作せず、

 border: solid 10px #003a66

としてボーダーの方で改造して幅を広げました。

フォームに関しては

.input-form {
  width: 94%;
  margin: 0.5% 0% 1% 1% ;
  padding: 0% 0% 0% 1%;
  float: left;
  border-radius: 10px;
  -webkit-appearance: none;
  border: 1px solid #ccc
}


.input-button
{
  width: 2%;
  max-width: 5%;
  height: auto;
  margin: 0.5% 0.5% 1% 1.5%;

}

こんな感じで書いております。
htmlは

<form method="post" action="/douinyosoku/1/">
  <input class = "input-form" name="input_text">
  <input class = "input-button" type="image" src="/static/css/images/submit_button.png" alt="送信する">
  <!--<input class = "input-button" type="submit" value="送信">-->
</form>


こうなっています。
送信ボタンをLINEっぽい画像にしたのですがこれをレスポンシブデザインに適用しようとすると大苦戦でした。


画像自体のサイズも最初からずいぶん変更しましたし、結局画面幅ごとにcssを書いていくという非常にオーソドックスな方法をとることに。

/* このやり方で画像を小さくすることにいつか挑戦したい。 https://junzou-marketing.com/responsive-image */
@media only screen and (max-width: 1024px){
.input-form {
  width: 94%;
  margin: 0.5% 0% 1% 1% ;
  padding: 0% 0% 0% 1%;
  float: left;
  border-radius: 10px;
  -webkit-appearance: none;
  border: 1px solid #ccc
}
}


@media only screen and (max-width: 1024px){
.input-button
{
  width: 2.5%;
  max-width: 2.5%;
  height: auto;
  margin: 0.5% 0.5% 1% 1.5%;

}
}


@media only screen and (max-width: 768px){
.input-form {
  width: 93%;
  margin: 0.5% 0% 1% 1% ;
  padding: 0% 0% 0% 1%;
  float: left;
  border-radius: 10px;
  -webkit-appearance: none;
  border: 1px solid #ccc
}
}


@media only screen and (max-width: 768px){
.input-button
{
  width: 3.5%;
  max-width: 3.5%;
  height: auto;
  margin: 0.5% 0.5% 1% 1.5%;

}
}


@media only screen and (max-width: 700px){
.input-form {
  width: 90%;
  margin: 0.5% 0% 1% 1% ;
  padding: 0% 0% 0% 1%;
  float: left;
  border-radius: 10px;
  -webkit-appearance: none;
  border: 1px solid #ccc
}
}


@media only screen and (max-width: 700px){
.input-button
{
  width: 7%;
  max-width: 7%;
  height: auto;
  margin: 0.5% 0.5% 1% 1.5%;

}
}


form幅と画像の幅を%表記でいじくっています。でもやっぱりちょっとずれるんですよね。
最近はこんな方法もあるらしくいつか最新の方法で挑戦したいです。

これが新常識! レスポンシブな画像切り替え方法まとめ


新常識ってなんかかっこいい。
ちなみにレスポンシブデザインの基本的なところはbootstrapにお任せ。
いまはこんな便利なものがあるんですね!!!すごい!!!

Introduction · Bootstrap
(Starter templateを使います。マジでなんかいい感じに処理してくれます)


元のプログラムの説明とcss周りだけで終わってしまった・・・。
続きは次回!