python line bot imagemap 画像送信
pythonでLINE botを作っていますが,
github.com
ここでだいたいわかります.しかし画像の送信とimagemapはサンプルがないので実装してみます.
画像送信
from linebot.models import ImageSendMessage def make_image_message(): messages = ImageSendMessage( original_content_url="https://hogehoge.jpg", #JPEG 最大画像サイズ:240×240 最大ファイルサイズ:1MB(注意:仕様が変わっていた) preview_image_url="https://hogehoge-mini.jpg" #JPEG 最大画像サイズ:1024×1024 最大ファイルサイズ:1MB(注意:仕様が変わっていた) ) return messages
これむっちゃ面白いんですけどプレビューとタップして表示される画像別になるんですよ!
注意:画像サイズの制限はもう少し大きく,jpgに限定されない.ただし.preview_image_urlにgifを指定しても,反映されない(正確にはアニメーションgifは動かない)ので注意
これを
messages = make_image_messages() line_bot_api.reply_message( event.reply_token, messages)
的にすればリプライできます.
imagemap
画像をボタン化できます.(画像は用意できれば用意します.)これの何がいいかというと
- 画像を見れることによる直感的操作
- 選択肢を増やせる(最大50)
from linebot.models import ImagemapSendMessage, BaseSize, ImagemapAction, URIImagemapAction, MessageImagemapAction, ImagemapArea def make_imagemap(): messages = ImagemapSendMessage( base_url='https://huhahaha/pikach/kawaii/', alt_text='this is an imagemap', base_size=BaseSize(width=1040, height=1040), actions=[ URIImagemapAction( link_uri='https://example.com/', area=ImagemapArea( x=0, y=0, width=520, height=1040 ) ), MessageImagemapAction( text='hello', area=ImagemapArea( x=520, y=0, width=520, height=1040 ) ) ] ) return messages
画像の保存の仕方に一癖あってけっこう悩みました.
https://huhahaha/pikach/kawaii/
以下に
幅:240px、300px、460px、700px、1040px
の画像を配置します.(横幅が指定であれば,高さは関係ない.また高さに合わせて,heightも変える)
なのですが,保存した画像の拡張子は**取ります**
(どっかで拡張子指定できるようにすればいいのに…)
参考にした
python win32client speak
import win32com.client as wincl
に関する記事が少なすぎるので,いくつかまとめます.
まず
speak.Speak("Hello World", i)
のiについてです
for n in range(2): speak.Speak("Hello World" + str(n), i) sleep(1) print(n)
で検証します.
- i = 0,2
これは
読み上げ->1秒待つ->print出力->読み上げ->1秒待つ->print出力となります
- i = 1
これは
読み上げと同時に一秒待ってprint出力(読み上げの途中で出力される)->出力から1秒後にprintされる.その間読み上げている(ただし,読み上げが重なることはない)
- i = 3
最初の文章の読み上げを1秒間行う->print出力->二行目を読み上げ(一行目は最後まで読み上げない)->一秒後にprint出力
for n in range(2): speak.Speak("Hello World" + str(n), i) sleep(1) speak2.Speak("Wow!", i) print(n)
- i = 1
Hello World 1->1->2->Hello World 2->Wow->Wow
になります.
どうなっているのかよくわからない.
python 読み上げ テキストファイル 一行ずつ 速度 変える キーイベント
タイトルが長いですが今回の要件を整理します
- pythonを使う
- 文字を読み上げる
- 内容はテキストファイルである
- キーイベントで一行ずつ読み上げる
って感じです.ちなみに今回はWindows10を使っています.Macではできません.
ではコード
import win32com.client as wincl import glob import os import random speak = wincl.Dispatch("SAPI.SpVoice") speak.Rate = -3 def read_files(): path = "テキストファイルまでのパス" f = open(path) lines = f.readlines() f.close() return lines def speak_lines(): lines = read_files() speak_line = -1 while True: input_word = input(""" コマンドを選んでください r->同じ行を繰り返して読む u->次の行を読み上げる d->前の行を読み上げる >""") if input_word == "u": if speak_line < len(lines) - 1: speak_line += 1 speak.Speak(lines[speak_line]) elif input_word == "d": if speak_line > 1: speak_line -= 1 speak.Speak(lines[speak_line])) elif input_word == "r": if 0 <= speak_line and speak_line < len(lines) - 1: speak.Speak(lines[speak_line]) elif input_word in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]: speak.Rate = int(input_word) - 6 if __name__ == '__main__': speak_scripts()
別のこといろいろしていたのでちょっと効率の悪いことしているのは許してください.
数字を入力すると読み上げスピードが変わります.全体的に見たままです.
speak.Speak("読み上げたい文章") speak.Rate = Long型 -> スピード(ピッチ?)の変更
python-osc 受信 可変長配列
import argparse from pythonosc import dispatcher from pythonosc import osc_server def print1(unused_addr, *p): print(p) //タプルで出力される def osc_loop(): parser = argparse.ArgumentParser() parser.add_argument("--ip", default="127.0.0.1", help="The ip to listen on") parser.add_argument("--port", type=int, default=12346, help="The port to listen on") args = parser.parse_args() _dispatcher = dispatcher.Dispatcher() _dispatcher.map("/read", print1) server = osc_server.ThreadingOSCUDPServer( (args.ip, args.port), _dispatcher) print("Serving on {}".format(server.server_address)) server.serve_forever() if __name__ == "__main__": osc_loop()
Arduino analog入力 足りない 増やす
意外とまとまっているサイトがなかったのでまとめておく。
Arduinoのアナログ信号はA0~A5の6つしかない。
が、増やす方法がないわけではない。
方法は二つ(初心者なので厳密にはいろいろ違うことを許してほしい)
・ADコンバータを使う
・MUX(マルチプレクサ)を使う
これら。デジタル信号を増やしたいときはIOエキスパンダーとか言うのがある。これも面白いのであとで記載したい。
とりあえず方法を教えろ、原理はあとで勉強するという人向けの記事であることを最初に述べておく。
まずADコンバータ
こんな回路になる。詳しい説明はいつか解説したい。
画像では薄くてわかりづらいが、小さな丸と凹みの部分をちゃんと確認してください(名前の方向は関係ない)
用いたのは
である。
コードは下に記載されている二つの記事のうち上のやつものがそのまま動く
電子部品使い方:マイコンのADC(MCP3208)変換
sites.google.com
参考にした記事
上記記事を見るといろいろ注意書きがあるので、ちゃんと使う人はちゃんと勉強した方がいいと思う。
次にMUX
こんな回路になる
用いたのは
である。
コードは下記ライブラリが古いが使える。
適当に描いたコードを
#include <Mux.h> Mux mux; int counter=0; void setup(){ Serial.begin(9600); mux.setup(5,4,3,2,A0); } void loop(){ int val = mux.read(counter); if(counter==15){ Serial.println(val); delay(1000); }else{ Serial.print(counter); Serial.print(":"); Serial.print(val); Serial.print(", "); } counter = ++counter & 15; delay(50); }
このうち0しか使っていないので、他の値は乱れがち
Flask SQLAlchemy alembicでtable、columnを作成したい。ついでにherokuにデプロイしたい
# sqlalchemy.url = driver://user:pass@localhost/dbname sqlalchemy.url = sqlite:///test.db
alebmic.initを正しいパスに変更する。
当たり前であるがこれを忘れて死んでいた。
Tutorial — Alembic 0.9.6 documentation
じゃあ、これをデプロイしようとして意外とはまった
floder構成は
+alembic env.py +versions +???.py app.py config.py alembic.ini
みたいな感じ
env.py
import app #app.pyから呼んでくる # #~そのまま~ # def run_migrations_online(): #下記を加える alembic_config = config.get_section(config.config_ini_section) alembic_config['sqlalchemy.url'] = app.app.config['SQLALCHEMY_DATABASE_URI'] connectable = engine_from_config( alembic_config, prefix='sqlalchemy.', poolclass=pool.NullPool) #上記を加える ''' #既存のコード connectable = engine_from_config( config.get_section(config.config_ini_section), prefix='sqlalchemy.', poolclass=pool.NullPool) ''' with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata ) with context.begin_transaction(): context.run_migrations()
stackoverflow.com
フォルダ構成が違うだけでこれが参考になる
python 暗号化 複合化 テキスト 保存
これの延長。暗号化した文字列をテキストファイルに保存したいという謎の欲求により生まれたコード
import base64 from Crypto import Random from Crypto.Cipher import AES import string, random class AESCipher(object): def __init__(self, key, block_size=32): self.bs = block_size if len(key) >= len(str(block_size)): self.key = key[:block_size] else: self.key = self._pad(key) def encrypt(self, raw): raw = self._pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(self.key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(self, enc): enc = base64.b64decode(enc) iv = enc[:AES.block_size] cipher = AES.new(self.key, AES.MODE_CBC, iv) return self._unpad(cipher.decrypt(enc[AES.block_size:])) def _pad(self, s): return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs) def _unpad(self, s): return s[:-ord(s[len(s)-1:])] def writeEncrypted(inputtext, filename, key): cipher = AESCipher(key) encryptedtxt = cipher.encrypt(inputtext) f = open(filename, 'w') f.write(str(encryptedtxt).split("\'")[1]) f.close() def openDecypt(filename, key): cipher = AESCipher(key) f = open(filename) data = f.read() f.close() print(cipher.decrypt(data.encode('utf-8'))) if __name__ == '__main__': key = ''.join([random.choice(string.ascii_letters + string.digits) for i in range(50)]) print(key) writeEncrypted("hogehuga", "hogehuga.txt", key) openDecypt("hogehuga.txt", key)
特殊なことはしていないんだけど
byte->strするときに
b'aiueo'
みたくなるので暗号化した部分だけ取りだす