Ngrokを使ってみようの巻
Ngrokを使ってみようの巻
こんばんは、葛の葉です。
さて、Ngrokというものがありまして、簡単なWebサーバーなら簡単に立ち上げることが出来るすぐれものがあるんです。
アカウントを入るように求められるのでGoogleとかのアカウントで好きに入ってください。
そしたらダウンロードが出来るのでインストールします。スゴイ。ここまでが準備。
flaskを公開してみようぜ
いつものhelloworldのプログラム(12行)
import flask app = flask.Flask(__name__) @app.route('/') def index(): return "Hello, World!" if __name__ == '__main__': app.run(debug=True, port=8080)
で起動するとlocalhost:8080
で繋がるはずです。127.0.0.1:8080
といったほうがいいかな?
いつもの画面が出てきた。
ngrokを落とすとngrok.exe
というものが出てきて、起動するとコマンドプロンプト
が立ち上がる。
このコマンドプロンプト
の画面で以下のコマンドを打ちましょう。
ngrok http 8080
なお、8080はポート番号です。flaskアプリのport=8080
と合致させましょう。そうしたら、下図の画面に移ります。
なんかよくわからんけど、https://f1fba471.ngrok.ioに繋がるようだぜ。もちろん、http://f1fba471.ngrok.ioもOK。
これでスマホでも見れるはず。
みられたねぇ!
コマンドプロンプト画面でctrl + c を押せばやめられます。
以上!!
python clova_sdkで開発しているんですよ -その1-
python clova_sdkで開発しているんですよ -その1-
久しく、お世話になっております。葛の葉です。
最近はclovaの開発を行っております。clovaの開発の記事はまだまだネット上には少ないので、今は公式のドキュメントを読み解きながらプログラミングをするという状況での開発を行っております。
前回の記事では、pythonにSDKが来たことと、そのpipでのインストール方法、そして、SDKのドキュメントのリンクなどを記載しました。
現在、clovaの開発用SDKのある言語は以下のようになるようですね。
↓引用元
SDKがあると、開発が簡単になりますね。使える言語がある人はチャレンジされてみてはいかがでしょうか?
それと、今回は私が開発をしていて、気になった点などを記載したいと思います。
clovaのしゃべるセリフが淡々としている
完全に個人的な感想なのですけど、抑揚とブレス、といいますか。人間っぽくない喋り方といいますか。意図してセリフを区切ったりしないと、淡々としゃべり続けてしまうのがclovaなのかなと思いました。(ほかのスマートスピーカーがどうかは知らないですけど…)ですので、長いセリフとかになりますと全部聞き取れないです。勉強の一環として色んなスキルを導入して使ってみていますが、セリフとしては1秒以内に区切りを入れたほうがいいのかな、と思いました。途中でよくなに喋ってるのかよくわからなくなりました。
ビルトインインテントとカスタムインテントの優先順位ってどっちなんだ?
「はい」や「いいえ」という言葉に反応する「ビルトインインテント」がありまして、個人的には「はい」「いいえ」も自分で作ったインテントで反応させたかったのですが、使ってみたところ「ビルトインインテント」が優先されているように感じました。というか、カスタムインテントで呼び出されることはありませんでした。「はい」も「いいえ」もそれぞれ同じインテントで受け取って、プログラミング内で、返答を変えたかったのですが…ちょっと残念。
最初はよくわからなかったsession_attributesという存在
clovaにはsession_attributesというものが存在しています。最初、これを理解することがなかなかできませんでしたが、やってみれば見るほど、必要な存在なのだなと認識するようになりました。session_attributesとは、clovaがスキルの起動中において、データとしてユーザーが発音した内容を記憶しておける部分になります。例えばユーザーが答えた「マカロニピザ」や「ペパロニピザ」というピザの種類の情報と「2枚」「3枚」という枚数の情報を、session_attributesに保存しておくことができます。その保存した情報を使って、プログラムを使ってピザ屋に情報を送信する、ということが可能になります。
import cek extensionId = '************skill.first' clova = cek.Clova(application_id=extensionId,default_language='ja', debug_mode=True) response_builder = cek.ResponseBuilder(default_language='ja') ~~~~~~~~ flaskだとかwebアプリ部分 ~~~~~~~~ # PizzaInntent(ピザの種類が呼ばれたときに呼び出されるインテント) @clova.handle.intent('PizzaIntent') def pizza_handler(clova_request): message = '何枚欲しいの?' end_session = False response = response_builder.simple_speech_text(message=message, end_session=end_session) response.session_attributes['pizza'] = clova_request.slot_value('pizzaName')
PizzaInntentが呼び出され、そのうち、pizzaName、ピザの種類を表す単語を取得します。 「マカロニピザを頼んで」という言葉のうち「マカロニピザ」という単語を取得します。
これをsession_attributesとして、{"pizza":"マカロニピザ"}というものに保存されます。
{ "response": { "card": {}, "directives": [], "outputSpeech": { "type": "SimpleSpeech", "values": { "lang": "ja", "type": "PlainText", "value": "何枚欲しいの?" } }, "shouldEndSession": false }, "sessionAttributes": { "pizza": "マカロニピザ", }, "version": "1.0" }
逆にsession_attributesから値を取り出す場合は
pizza = clova_request.session_attributes['pizza']
のような形になります。
このように、ユーザーがしゃべった内容を受け取ることで、プログラミング側であれこれ出来るようになるのです。
私、プログラミング歴短いんですけど、Clovaの開発を通して色々なことを学べていっていけているように感じます。とりあえず、今日は気になったところをサクッと書いてみました。来週もclovaについて書いていきます。よかった次も見ていってください。
ClovaSDKのPythonVerがあるのだ
ClovaSDKのPythonVerがあるのだ
こんばんは、葛の葉です。
先日、駅すぱあとのヴァル研究所さんで行われたハンズオンに出席しました。
Lineさんが作っているスマートスピーカーの「Clova」の「スキル」の開発についての勉強会だったのですが、これが中々に面白い体験でした。正直、スマートスピーカーを触ったのが今回はじめてだったのですが、「スキル」を開発出来てとても面白かったです。
そんな「Clova」の開発用のPythonで使用できるSDKが出たということで、そのドキュメントのリンクを張っておきます。
こちら↓
Clova Extension Kit SDK for Python — clova-cek-sdk 1.0.0 documentation
なお、PythonのClovaSDKはpipでインストールすることが出来ます。
pip install clova-cek-sdk
モジュールとして使うときはimport cek
で使います。
import cek
ちょっとSDKとは直接関係ないお話
スキルって?
スマートスピーカーを触ったことがなかった私には「スキル」という言葉がよくわからなかったです。いわゆる、スマートフォンにおける「アプリ」のようなものでして、機能の一単位のことになるようです。それで、今回のClovaSDKはそのスキルを作成できるものとなっています。
Clova Friendsってどんな感じ?
Clova Friendsの大きさは500mlの缶ジュースより少し高さがあるくらいで、太さは500mlのペットボトルぐらいな気がしますClova Friends miniは持っていないのですが、Clova Friendsの半分ぐらいじゃないでしょうか?
なんと、内臓バッテリー付きです。Bluetoothでスマホと接続して音楽などを流したりすることもできますので、Clova Friendsを屋外に持ち出して、外で音楽を流すっていうこともできますね。一つ思いついた遊びとして、スマホで演奏するアプリを使って、Clova Friendsで流すなんてやれたら面白いかもなぁなんて思いました。
スキル、としては、ネットワークに繋がっていることが前提なものが多いように見受けられますので、外部に持ち出す部分とは少し相性悪いのかも?とは正直に思いました。
若干、最近スマートスピーカーに焦点が当たりつつあると思ってます。
皆さんもぜひ、色々なスマートスピーカーを触ってみてください。
Pythonで特定文字以降の文字を削除する(正規表現を使わない)
Pythonで特定文字以降の文字を削除する(正規表現を使わない)
イテレータで作ったVerがありますので、よかったら以下もどうぞ
こんばんは、葛の葉です。
さて、APIなどで、文字列を取得することがあると思うのですが、余分な部分は無くして綺麗な形で変数や配列に入れたいと思うことが多々あると思います。
たとえば町田(東京)
の(東京)
部分
たとえばシェフの気まぐれサラダ(工場生産)
の(工場生産)
の部分
たとえばからあげ:20180810
の:20180810
の部分
正規表現で削除することも出来るのですが、私はこんなやりかたをしてみました。
moji = 'シェフの気まぐれサラダ(工場生産)' moji = moji.split('(')[0] print(moji) >>>シェフの気まぐれサラダ
>>>シェフの気まぐれサラダ
出来ました!!!
要するにsplit('(')
を使って(
を境に文字を区切って配列にしています。
moji.split('(')
は['シェフの気まぐれサラダ', '工場生産)']
という配列になりますね。
その[0]
番目の要素を取り出すのでシェフの気まぐれサラダ
の部分だけ取り出すことが出来るわけですねぇ。
ただ、配列に分解して取り出しているだけなので、複雑な文等には適していないと思います。
切りたい文字が入っている要素、入っていない要素の入子になっている配列での取り出し方
また、例えば配列の中に括弧()
が入っている、入っていないものが入子になっている配列もあるかと思います。
dinners = ['チキングリル', 'シェフの気まぐれサラダ(工場生産)', 'ドラゴンのしっぽビール(発泡酒)', 'スコーン']
こんな場合は以下のようにしてみましょうか
dinners = ['チキングリル', 'シェフの気まぐれサラダ(工場生産)', 'ドラゴンのしっぽビール(発泡酒)', 'スコーン'] cut_dinners = [] # 入れ替える別配列を用意しておく for dinner in dinners: if '(' in dinner: cut_dinners.append(dinner.split('(')[0]) else: cut_dinners.append(dinner) print(cut_dinners) >>> ['チキングリル', 'シェフの気まぐれサラダ', 'ドラゴンのしっぽビール', 'スコーン']
if '(' in dinner:
という方法をとると良いですね。
文字列内に(
があるか…?を判定し、
Trueならcut_dinners.append(dinner.split('(')[0])
Flaseならcut_dinners.append(dinner)
とします。
API等を使うと色んな値が入った文字列と出会うようになったなぁと思ってます。
その文字列を加工していくことも、すごく重要ですよね。
API使って開発されている皆様のお役に立てれば幸いです。
DockerでflaskとuWSGIを別コンテナのNginxと連携してみた
DockerでflaskとuWSGIを別コンテナのNginxと連携してみた
こんばんは、葛の葉です。
さて、よくNginx
とuWSGI
を使ってWebサーバー
の構築をしている記事は見かけますが、
同じコンテナ内でNginx
とuWSGI
をインストールしているケースが多く、
Nginx
とuWSGI
と別コンテナで構築しているケースがあまり無いのかな、と思いました。
DockerCompose
を使った場合になるのですが、簡単に書いていきたいと思います。
なお、もっといいケースなんてたくさんあると思うので、むしろ教えて頂ければと思います。
まず、docker-compose.yml
が必要で、更にIPアドレスを固定化するか、コンテナネームを固定化したほうがよいです。
それは記事にしましたので、下に載せます。
コンテナネームの固定化について
コンテナのIPアドレスの固定化について
flaskのあるコンテナでの設定
uWSGI
が必要なため、flask
のあるコンテナでpipでインストールします。
pip install uwsgi
また、設定ファイルが必要なので、uwsgi.ini
というデータを作り、以下のように記載します。
[uwsgi] http = :3031 #ここはuwsgiのポート番号 chdir = /var/www/ #下記、flaskで実行したいプログラムのあるディレクトリ wsgi-file = page.py #flaskのプログラム callable = app #flaskを実行するためにここは不変更
そして、コマンドでuwsgi --ini uwsgi.ini(先程のuwsgi.ini)
として、実行すればよいです。
これをdocker-composeでのcommand
で設定すれば、コンテナが起動するときに指定したコマンドが実行されるはずです。
command: uwsgi --ini uwsgi.ini
とすればよいです。
uwsgi.ini
をホストマシンから持ってくるにはvolumes
で共有すればよいので、
例えばdocker-compose.yml
のあるディレクトリにapp/config
ディレクトリを作り、
そのapp/config
以下に先程のuwsgi.ini
を保存しておき、docker-compose.yml
で以下のように記載して共有します。
また、docker-compose up
時にuwsgi.ini
を起動するようにしておきます。
volumes: - ./flask_app/config/:/var/www/config/ command: uwsgi --ini /var/www/config/uwsgi.ini
とこのようにしておきます。
Nginxのあるコンテナでの設定
Nginxは/etc/nginx/nginx.conf
の設定を変えてあげればうまくいきます。
また、そのnginx.conf
をホストOSで作ってあげて、渡してあげればよい、ということになります。
ホストOSにnginx.conf
を持ってくる方法はとりあえず記載しないとして
(一度、Nginxコンテナ単体で起動して、共有のフォルダにコピーしてホストOSに持ってくる等)
設定ファイルのlocation
部分を以下のようにの設定します。
location / { client_max_body_size 1m; client_body_buffer_size 8k; proxy_pass http://[flaskのあるコンテナネームorコンテナのIPアドレス]:3031; proxy_redirect default; }
これを、例えばdocker-compose.yml
のあるディレクトリにnginx/config
ディレクトリを作り、
そのnginx/config
以下に先程のnginx.conf
を保存しておき、docker-compose.yml
で以下のように記載して共有します。
volumes: - ./nginx/config/nginx.conf:/etc/nginx/nginx.conf
直接、Nginxのnginx.conf
ファイルに共有してあげます。
専用のconf
をつくって、そこに読みに行くような設定もありますが、ちょっとこちらでは記載しません。(Nginxの設定方法の話になるので)
docker-compose upする
この状態でdocker-compose up
すると、nginxで開放したポート番号に接続すれば、flaskのアプリが起動するはずです。
DockerComposeでContainerのIPアドレスの固定化をするかー
こんばんは、葛の葉です。
久しぶりにDockerのことを書こうと思いました。
今回はDocker-ComposeでcontainerのIPアドレスを固定化を行いました。
networks: aplication_net: ipv4_address: 172.19.x.x
DockerComposeで各コンテナの設定部分に上記の部分を記載すればよいです。
aplication_net
はDockerNetworkの名称になります。
ipv4_address: 172.19.x.x
は使用するIPアドレスです。
また、コンテナ間にDockerNetworkを構成する記述を行います。
networks: aplication_net: driver: bridge ipam: driver: default config: - subnet: 172.19.0.0/24
aplication_net:
部分はDockerNetwork名を記載します。
subnet: 172.19.0.0/24
は使用したいネットワークアドレスとそのサブネットマスクをプレフィックス長で記載します。
なお、cofig:
下ではgateway:
というプロパティ、デフォルトゲートウェイの設定もあるそうなのですか、v3
では出来ないようです。
デフォルトゲートウェイがどういうIPアドレスであるかが不明なため、今回は172.19.0.1
を想定しています。
docker-compose.yml
は以下の通りになります。
services: mysql: image: ./mysql ~~~~~~~~~~~中略~~~~~~~~~~~~~~~~~~ networks: aplication_net: ipv4_address: 172.19.0.2 app: build: ./app ~~~~~~~~~~~中略~~~~~~~~~~~~~~~~~~ networks: aplication_net: ipv4_address: 172.19.0.3 nginx: image: nginx ~~~~~~~~~~~中略~~~~~~~~~~~~~~~~~~ networks: aplication_net: ipv4_address: 172.19.0.4 networks: aplication_net: driver: bridge ipam: driver: default config: - subnet: 172.19.0.0/24
docker-compose up
でコンテナを起動しましょう。
docker exec -it コンテナ名 /bin/bash
でコンテナ内に入り、hostname -i
でIPアドレスを確認してみましょう。
root@xxxxxxxxxxxx:/# hostname -i 172.19.0.3
IPアドレスが表示されました!
GSSとGASとDiscordで遊んじゃおう
GSSとGASとDiscordで遊んじゃおう
こんにちは、葛の葉です。
GoogleSpreadSheet
ってあるじゃあないですか。
このGoogleSpreadSheetにscriptを実装できるようになっていて
それがGoogleAppsScript
っていうやつになります。
さらに、そのGoogleAppsScriptを使ってDiscord
と連携できるようになります。
今回はGoogleSpreadSheetのセルの中身をGASで取得してDiscordに発信するbotを
作りたいと思います。
必要な材料
- Googleアカウント
- Discordアカウント
- Discordのノリにそれなりについていける心
好きなシートを作るんだ
好きなシートを作りましょう。
A1
セルに好きな言葉も入れておきましょう。
ちなみに私葛の葉
って名前だけど、これ元は雌の狐の名前なので
よーく考えたら男なのに女性の名前使ってましたね。
まぁ…いいか…
スクリプトエディタ起動
右上に[ツール]タブ
があって、そのメニューにスクリプトエディタ
っていうのがありますので
クリックすると別画面が開いて、それがスクリプトエディタが表示されます。
こんな画面がスクリプトエディタです。
DiscordのWebhookを起動
botとして出力させたいDiscordのチャンネルで歯車のボタンを押します。
そこから画面左側の[Webhooks]
→[Webhooks作成]
をクリックします。
出てきた画面には好きなbotの名前やアイコンを設定して保存しましょう。
そうしたら画面右側に作ったbotが表示されていると思うので[編集]
を押します。
さっきbotを作った画面に似たようなものが出てきますが、その下にスクロールすると
URL[画面の赤い四角部分]が表示されていますので、これをコピーします。
コピーしたURLをブラウザーで開くと何やらいろいろ書かれたものが出てきますが、
"token: "
の右側の色んな文字数字をコピーしておいてください。
スクリプトエディタでコードを書く
function submit(){ discord(get_value()) }; function get_value() { var sheet = get_sheet('自分の作ったシートのURL',0); var range = sheet.getRange(1,1); //ここの(1,1)は座標です。第一引数が行、第二引数が列です。 var value = range.getValue(); return value; }; function get_sheet(gss_url,sheet_num) { var ss = SpreadsheetApp.openByUrl(gss_url); var sheet = ss.getSheets()[sheet_num]; return sheet; }; function discord(message) { const url = 'さっきコピーしたwebhooksのURL'; const token = 'さっきのURLの中のtokenの文字列'; const channel = '#general'; const text = message; const username = 'bot'; const parse = 'full'; const method = 'post'; const payload = { 'token' : token, 'channel' : channel, "content" : text, 'username' : username, 'parse' : parse, }; const params = { 'method' : method, 'payload' : payload, 'muteHttpExceptions': true }; response = UrlFetchApp.fetch(url, params); }
関数の実行
関数を選択
を押すとプルダウンがでてきますのでsubmit
を押してください。
実行ボタンを押すとスクリプトエディタの上部になんかメッセージが出てきます。
権限がどうのって聞いてきますが、ポチポチ押せばOKです。
そしたら、葛の葉
ってメッセージが#general
に表示されるはず!
A1
の値を変えてもいいですし、sheet.getRange(1,1)
の(1,1)
の値を変えてみるのも面白いですよ!