エンジニア

なんくるないさ

「このブログはアフィリエイト広告を利用しています」

Herokuを使って、pythonのウェブアプリ(サービス)を外部公開した方法

今回はローカルで動く要約ウェブアプリをherokuで公開する方法をざっくり紹介します。

下にそのリンクを貼っておきます。
パソコンはchromeでしか動きません。
スマホはアンドロイドとiphoneで動きました。
要約君

手順は以下の通りです。

2がすごいわかりにくく苦戦しました(今も)

1.ローカルウェブアプリをつくる
2.herokuに登録して、デプロイ
3.今後の課題とデータベースについて

このような流れで説明します。

私の環境ですが、

windows10

python 3.6.5

です。

1.ローカルウェブアプリを作る。

pythonのkerasを使ってバックエンド、jsとhtmlでフロントエンドを作る。 このような感じで書きました。

import time
import random
#scientific computing library for saving, reading, and resizing images
#from scipy.misc import imsave, imread, imresize
#import codecs

#for matrix math
import numpy as np
#for regular expressions, saves time dealing with string data
import re

#system level operations (like loading files)
import sys 

import jabstract

import summarize
#initalize our flask app

import pandas as pd
import psycopg2


import datetime

app = Flask(__name__)




@app.route('/')
def index():
    with open("summarize.html", "rb") as f:
        return render_template('summarize.html')

@app.route('/predict/',methods=['GET','POST'])
def predict():
    #print((request.get_data()).decode('utf-8'))
    #一次元の配列
    label = (request.get_data()).decode('utf-8')
    #label = urllib.parse.unquote(label)
   # label =  label.encode().decode('unicode-escape')
    #label = urllib.parse.unquote(label,'shift-jis')
    #lablel = label.encode().decode('shift_jis')
    #shape = str(type(label))
    #name1,name2,name3,name4,name5 = label.split("&")
    
    name1,name5 = label.split("&")
    
    #文書全体 exampole= "文章---"だから8個めから文章全体がはじまる。
    name1 = name1[8:]
    
    #要約文字数
    name5 = name5[6:]
   
    
    name1= urllib.parse.unquote(name1)
    name5= urllib.parse.unquote(name5)
    
    sentence = name1
    num = name5
    
    print(num,sentence)
    
    sum_sentence,sum_num = summarize.dosum(num,sentence)
    
    """
    #DBに追加して、書き込み
    #データベース接続のため
    connection = psycopg2.connect("...")
    cursor = connection.cursor()
    cursor.execute("select version()")

    #時間確保のため


    dt_now = datetime.datetime.now()
    #print(dt_now)
    dt_now = str(dt_now)
    #print(dt_now)
    
    cursor.execute("INSERT INTO test2 (time, input, output) VALUES (%s, %s, %s)", (dt_now, sentence, sum_sentence))
    cursor.execute("SELECT * FROM test2;")
    cursor.fetchone()
    connection.commit()
    cursor.close
    connection.close()
    """
    
    return json.dumps({
        "参照サイト数":sum_sentence,
        "要約文字数":str(sum_num),

    },ensure_ascii=False)
    
    
    
if __name__ == "__main__":
    app.run(debug=True,port=8084)
    print("http://localhost:" + str(port))

ウェブページは下のような感じです。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>要約君</title>
<!--
    <link rel="stylesheet" href="./static/style.css">
  -->
</head>
<body>

<form  id="my-form">

<p>文章入力欄</p>
<textarea name="example" cols="150" rows="20">
要約する文章を入力してください。
</textarea>

<p>要約文字数:<br>
<input type="text" name="name5" size="30" value=200 ></p>

<p><input type="button" value="要約する" id="submit" onclick="disabled = true;"></p>

<input type="button"
   value="検索する解除"
   onclick="getElementById('submit').disabled = false;">

</form>
<div >
  <h1 id="result" style="margin-right:20px; margin-top:1px;float:left;"><span> </span></h1>
</div>
<script type="text/javascript" src="../static/jquery-3.3.1.min1.js"></script>

<script type="text/javascript">
$("#submit").click(function(){
    var val1 = $('#my-form [name=example]').val();
    console.log(val1);
    var val5 = $('#my-form [name=name5]').val();
    console.log(val5);
    event.preventDefault();

//送る文字列定義
    var kei = val1 +","+val5;
    console.log(kei);
    var $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
    $.ajax({
      type: "POST",
      url: $SCRIPT_ROOT + "/predict/",
      data:$('form').serialize() ,

      success: function(data){
        $('#result').text(' 推測結果: '+data);
      },
      error: function(data){
         $('#result').text('データ不足です');
      }
    });

});


</script>
<a href="https://px.a8.net/svt/ejp?a8mat=35AWZT+9IC9MA+48ZS+60WN5" target="_blank" rel="nofollow">
<img border="0" width="300" height="250" alt="" src="https://www28.a8.net/svt/bgt?aid=190305929575&wid=001&eno=01&mid=s00000019828001012000&mc=1"></a>
<img border="0" width="1" height="1" src="https://www14.a8.net/0.gif?a8mat=35AWZT+9IC9MA+48ZS+60WN5" alt="">

</body>
</html>

2.herokuに登録して、デプロイ

上のプログラムやらが置いてあるフォルダに移動します
1.windows + R からcmdで検索してコマンドプロンプト起動
2.cd .\ ほにゃららで行けます。私の場合 cd .\recruit でした

そこに仮想環境を作ります(多分最初から仮想環境つくってそこで作業していたほうが良いのかも?) この仮想環境て必要なの?て思う人がいるかもしれません  
僕もそのうちの一人でした

最初は無視してやっていたのですが、requirements.txtを作るときに積みます。。。無駄ならライブラリまで書き込まれちゃいます
やってみるといいかもね

話を戻します
windowsでは仮想環境にcmd
.\venv\Scripts\activate
で入れます。(もうこのコマンド覚えてしまった)
作ってない方はpython3 -m venv venv
で作りましょう。
入った後は
pip install numpy とか色々必要な、使っているライブラリを手動で一個ずつインストールします。  (ウェブアプリで使っているライブラリだけを自動で、インストールする方法があれば教えてください。。。)
んで全部いけたら
cmdで pip freeze > requirements .txtでライブラリが書き込まれた.txtを作ります
他にもProcfile runtime.txtも作らないといけないよ。(ここは特につまずなかったので他サイト参照してください)
ちなみにProcfileの中身の「web: gunicorn app5:app --log-file=- 」のapp5はflaskとかを動かす起動プログラムの名前です
僕の場合はapp5.pyという名前だったのでこうなります

いよいよgitを使います
git登録してない人はここで登録しておきます

んで仮想環境はいったままでも、抜けたままでもいいので、ウェブプログラムがあるフォルダで(僕の場合.\recruit)

git add . (初めての人はgit initしてから)
git commit -m"ほにゃらら"
git push heroku master
heroku open でページが公開されます
エラーが出るかもしれませんが、ネット調べれば情報が出てきてそれで解決できました

3.今後の課題とデータベースについて

今後の課題のでは、ユーザが入力したデータをデータベースにいれてheroku上に保存したいと考えています。
(いまトライしていますが、色々エラーがでて前に進めていません。タイムアウトエラーだったり、アプリケーションクラッシュエラーだったり。助けてくださいい)  
データベースはにはユーザが入力したデータと日時、要約結果を入れる予定です。  
ローカルでは動くことが確認できていますが、、、ネットに挙げるとそもそもそのページが開かないという。。。  

追伸

herokuで上手く動かない問題なのですが、    f:id:jump1268:20190316144825p:plain
最初は次のような感じでjanomeのエラー?からアプリクラッシュが起こり、URLにアクセスするとAppcation errorとなっています。  

(原因はわからないのですが)そのエラーが起こらなかった場合は  
f:id:jump1268:20190316145006p:plain
このようにタイムアウトのエラーがでます。

色々調べてると。。   cmd で
heroku run rake db:migrate
heroku restart  
するとうまくいくよ的なものをみつけたのでそれをしてみるとエラーが出ないようになりました。

なぜうまくいっているのかがよくわかりません。データベース関連のことだと思いますが。

次回はデータベースについてです。コメント等あればお待ちしております

jump1268.hatenablog.com

私事ですが、下のサイトに登録したらオファーが一件届きましたが、全然好みじゃなかったので断りました。ごめんなさい 就活も頑張っていきたいと思います。