・ Seit ich umgezogen bin, benutze ich den Bus zum Pendeln. ・ Ich mache mit einem iPhone ein Foto des Busfahrplans und überprüfe es nacheinander anhand der "Fotos". ・ Die Pendelstrecke ist [Heimat ↔︎ (Bus) ↔︎ Nächster Bahnhof ↔︎ (Zug) ↔︎ Firmenbahnhof], besonders auf dem Rückweg möchte ich in den Bus einsteigen, sobald ich am nächsten Bahnhof ankomme. ・ Es ist mühsam, den nächsten Vorgang jedes Mal auszuführen, wenn Sie die Buszeit überprüfen. (Starten Sie die Foto-App auf Ihrem iPhone.) → (Suchen Sie nach der Buszeit aus der Foto-App.) ・ Ich möchte die Buszeit effizienter kennen. ・ Ich möchte mit Python, LINEBot usw., die ich studiere, etwas Nützliches für mein Leben schaffen. ・ Obwohl ich fleißig lerne, habe ich es satt, Apps zu erstellen, die Menschen imitieren. ・ Das Obige ist der Hintergrund dieser Anwendungserstellung. (Achtung) Die Quelle ist ein Anfänger, daher ist sie schmutzig (bitte vergib mir). (Hinweis) Ich nehme den Zeitplan aus der CSV-Datei, teste ihn in der lokalen Umgebung und stelle ihn dann in Heroku bereit (möglicherweise gibt es einen effizienteren Weg).
↓↓↓↓↓↓↓ (Fertiggestelltes Bild) ↓↓↓↓↓↓↓↓ Wenn Sie "Go" an LINE Bot senden, werden das Bild des Busses, die Buszeit von der Bushaltestelle, die Ihrem Haus am nächsten zum Bahnhof liegt, und die nächste Buszeit zurückgegeben. Wenn Sie "Zurück" sagen, wird die Buszeit vom nächsten Bahnhof zur nächstgelegenen Bushaltestelle zurückgegeben.
・ So erstellen Sie einen LINE Bot-Kanal ・ Details zur Bereitstellung in Heroku
(1) Hintergrund der Anwendungserstellung (2) Was in diesem Artikel nicht zu schreiben ist und die Struktur des Artikels (3) Umweltbau (4) Funktionsprüfung in lokaler Umgebung (5) Mit Heroku in den LINE Bot integrieren
· Mac ・ Python3 ・ Sqlite3 ・ Postgresql ・ Heroku · Flasche
Erstellen Sie zunächst ein Verzeichnis linebot_jikokuhyou auf dem Desktop, erstellen Sie eine virtuelle Umgebung im Verzeichnis und starten Sie es.
python3 -m venv .
source bin/activate
Testen Sie zunächst in Ihrer lokalen Umgebung. Die Datenbank verwendet SQL. Importieren Sie die zuvor vorbereitete CSV-Datei in SQL und überprüfen Sie, ob das Programm lokal lokal mit Flask funktioniert.
Bereiten Sie das Verzeichnis und die Dateien wie unten gezeigt vor. Verwenden Sie für iki.csv und kaeri.csv die von Ihnen selbst erstellten Dateien (später beschrieben). Andere als die oben genannten Dateien werden als leere Dateien erstellt.
linebot_jikokuhyou
├csv_kakou.py
├csv_to_sql.py
├local_main.py
├jikoku_main.py
├assets
│ ├database.py
│ ├models.py
│ ├__ini__.py
│ ├iki.csv (von Ihnen selbst erstellte CSV-Datei)
│ └kaeri.csv (von Ihnen selbst erstellte CSV-Datei)
│
└templates
├test.html
└test2.html
-Der folgende Zeitplan wird als CSV-Datei (Beispiel) erstellt. (↓↓↓↓↓↓ Busfahrplan von der Haltestelle in der Nähe Ihres Hauses zum nächsten Bahnhof) (↓↓↓↓↓↓ Busfahrplan vom nächsten Bahnhof zur Haltestelle in der Nähe Ihres Hauses)
.py:csv_kakou.py
#iki.Verarbeitung von CSV
list = []
with open('assets/iki.csv',encoding='utf-8')as f:
#Prozess zum zeilenweisen Lesen
for i in f:
columns = i.rstrip()
list.append(columns)
list2 = []
for i in list:
columns2 = i.split(',')
for ii in range(len(columns2)):
if ii != 0:
list2.append(columns2[0]+'Zeit'+columns2[ii]+'Protokoll')
list2.pop(0)
num = 1
with open('assets/jikoku.csv','w',encoding='utf-8')as f:
go_or_come = 'Gehen'
for time in list2:
f.write(str(num) +','+time+','+str(go_or_come)+'\n')
num+=1
#kaeri.Verarbeitung von CSV
list = []
with open('assets/kaeri.csv',encoding='utf-8')as f:
#Prozess zum zeilenweisen Lesen
for i in f:
columns = i.rstrip()
list.append(columns)
list2 = []
for i in list:
columns2 = i.split(',')
for ii in range(len(columns2)):
if ii != 0:
list2.append(columns2[0]+'Zeit'+columns2[ii]+'Protokoll')
list2.pop(0)
with open('assets/jikoku.csv','a',encoding='utf-8')as f:
go_or_come = 'Rückkehr'
for time in list2:
f.write(str(num) +','+time+','+str(go_or_come)+'\n')
num+=1
・ ↓↓↓↓↓↓↓ Die im Assets-Verzeichnis erstellte Datei jikoku.csv lautet wie folgt (Teilauszug). Insgesamt gibt es 64 Datensätze.
Erstellen Sie jedes im Assets-Verzeichnis.
.py:database.py
#coding: utf-8
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session,sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import datetime
import os
database_file = os.path.join(os.path.abspath(os.path.dirname(__file__)),'data.db')
engine = create_engine('sqlite:///' + database_file,convert_unicode=True,echo=True)
db_session = scoped_session(
sessionmaker(
autocommit = False,
autoflush = False,
bind = engine
)
)
Base = declarative_base()
Base.query = db_session.query_property()
def init_db():
#Importieren Sie Modelle in den Assets-Ordner
import assets.models
Base.metadata.create_all(bind=engine)
.py:models.py
#coding: utf-8
from sqlalchemy import Column,Integer,String,Boolean,DateTime,Date,Text
from assets.database import Base
from datetime import datetime as dt
#Informationen zur Datenbanktabelle
class Data(Base):
#Einstellungen für Tabellennamen,Auf Namen benennen
__tablename__ = "data"
#Setzen Sie die Spalteninformationen und setzen Sie sie eindeutig auf False (was bedeutet, dass der gleiche Wert akzeptiert wird).
#Der Primärschlüssel wird bei der Suche nach einer normalerweise festgelegten Zeile benötigt
id = Column(Integer,primary_key=True)
#Beurteilen Sie, ob Sie gehen oder zurückkehren möchten
go_or_come = Column(Text,unique=False)
#Nummerierung getrennt vom Hauptschlüssel
num = Column(Integer,unique=False)
#Zeit im Stundenplan
time = Column(Text,unique=False)
#timestamp
timestamp = Column(DateTime,unique=False)
#initialisieren
def __init__(self,go_or_come=None,num=0,time=None,timestamp=None):
self.go_or_come = go_or_come
self.num = num
self.time = time
self.timestamp = timestamp
-Erstellen Sie eine Datei csv_to_sql.py, die CSV-Daten liest und in SQL-Daten schreibt.
.py:csv_to_sql.py
from assets.database import db_session
from assets.models import Data
#Initialisierungsprozess
from assets.database import init_db
init_db()
#Verarbeitung zum Schreiben von CSV nach SQL
with open('assets/jikoku.csv',encoding='utf-8')as f:
for i in f:
columns = i.rstrip().split(',')
num = int(columns[0])#num ist Modelle.Da es in py als int-Typ definiert ist, wurde es als int-Typ erstellt
time = columns[1]
go_or_come = columns[2]
row = Data(num=num,time=time,go_or_come=go_or_come)
db_session.add(row)
db_session.commit()
-Initiate SQL mit init_db ().
sqlite3 data.db
Wenn Sie in SQLite Folgendes eingeben,
select * from data;
Folgendes wurde ausgegeben, und ich konnte bestätigen, dass die Daten in SQL geschrieben wurden.
.py:jikoku.py
from assets.database import db_session
from assets.models import Data
import datetime
def jikoku_search(route):
#Lesen Sie SQL
data = db_session.query(Data.num,Data.time,Data.go_or_come,).all()
#Aktuelles Datum und Uhrzeit abrufen (Datum / Uhrzeit-Typ)
date_todaytime = datetime.datetime.today()
#Konvertieren Sie das Obige in den Typ str
str_todaytime = date_todaytime.strftime('%Y Jahr%m Monat%d Tag%Uhr%M Minuten')
#Vom aktuellen Datum und der aktuellen Uhrzeit wird nur ● Jahr ● Monat ● Tag erfasst(Datumstyp)
date = datetime.date.today()
#Konvertieren Sie das Obige in den Typ str
str_date = date.strftime('%Y Jahr%m Monat%d Tag')
#Variablen setzen
bustime = ''
next_bustime = ''
#Route klassifiziert das Gehen und Zurückkehren
route = route
#Extrahieren Sie die Abfahrtszeit des letzten Busses und die Abfahrtszeit des nächsten Busses von sql
for i in data:
str_sql = i[1]
#Fügen Sie das aktuelle Datum und die aktuelle Uhrzeit ● Jahr ● Monat ● Tag zur Uhrzeit von sqr hinzu, um es zu „Datum und Uhrzeit“ zu machen.
str_sql_rr = str_date + str_sql
#Konvertieren Sie das Obige in den Datum / Uhrzeit-Typ
date_sql_rr = datetime.datetime.strptime(str_sql_rr,'%Y Jahr%m Monat%d Tag%Uhr%M Minuten')
#Ermitteln Sie das Datum und die Uhrzeit des letzten Busses im Vergleich zum aktuellen Datum und der aktuellen Uhrzeit
if date_sql_rr > date_todaytime and i[2]== route:#go_or_Wenn die Route übereinstimmt, gehen Sie wie folgt vor
#Ermitteln Sie die Differenz zwischen dem Abfahrtsdatum und der Abfahrtszeit des letzten Busses und dem aktuellen Datum und der aktuellen Uhrzeit
date_sabun = date_sql_rr-date_todaytime
#Die Differenz von Datum und Uhrzeit ist vom Typ Zeitdelta. Da der Timedelta-Typ mit strftime nicht zum str-Typ gemacht werden kann, wird str()In str Typ gemacht
#Der Timedelta-Typ ist 0:00:Da es 00 ist und die Differenz innerhalb von 1 Stunde vom Zeitplan liegt, werden "Minuten" durch Schneiden extrahiert.
if str(date_sabun)[0:1] == "0":
bustime = 'Der nächste Bus ist'+str_sql_rr+'Abfahrt nach.' + 'nach' + str(date_sabun)[2:4] + 'Es sind Minuten.'
else:
bustime = 'Der nächste Bus ist'+str_sql_rr+'Abfahrt nach.' + 'nach'+ str(date_sabun)[0:1] + 'Zeit' + str(date_sabun)[2:4] + 'Es sind Minuten.'
#Erhalten Sie die Nummer des Abfahrtsdatums und der Abfahrtszeit des nächsten Busses
next_num = i[0]
#Holen Sie sich die Abfahrtszeit des nächsten Busses (Verarbeitung, wenn der neueste Bus vorhanden ist, der nächste Bus jedoch den letzten Zug überschreitet)
try:
_next_bustime = db_session.query(Data.num,Data.time,Data.go_or_come).all()[next_num].time
#Fügen Sie das aktuelle Datum und die aktuelle Uhrzeit ● Jahr ● Monat ● Tag zur Abfahrtszeit des nächsten Busses hinzu, um "Datum und Uhrzeit" festzulegen.
next_bustime = str_date + _next_bustime+'Abfahrt nach.'
except:
next_bustime="Es ist über den letzten Zug."
#Verarbeitung zum Beenden der for-Anweisung nach Abrufen der Buszeit
break
#Verarbeitung, wenn der letzte Zug für den letzten Bus und den nächsten Bus vorbei ist
else:
bustime="Der nächste Bus fährt am letzten Zug vorbei."
next_bustime="Der nächste Bus fährt auch über den letzten Zug."
return bustime,next_bustime
-Erstellen Sie local_main.py, um zu überprüfen, ob jikoku.py in der lokalen Umgebung ordnungsgemäß funktioniert.
.py:local_main.py
from flask import Flask,request,render_template
from assets.database import db_session
from assets.models import Data
import jikoku_main as jm
app = Flask(__name__)
@app.route('/')
def test():
#Lesen Sie aus SQL
data = db_session.query(Data.num,Data.time,Data.go_or_come,).all()
return render_template('test.html',data=data)
@app.route('/iki')
def test2():
result1,result2 = jm.jikoku_search('Gehen')
return render_template('test2.html',bustime=result1,next_bustime=result2)
@app.route('/kaeri')
def test3():
result1,result2 = jm.jikoku_search('Rückkehr')
return render_template('test2.html',bustime=result1,next_bustime=result2)
if __name__ == '__main__':
app.run(debug=True)
Erstellen Sie jedes im Vorlagenverzeichnis wie folgt.
.html:test.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<title>Jikokuhyou</title>
<style>body{padding:10px;}</style>
</head>
<body>
<form action='/iki' method='get'>
<button type='submit'>Gehen</button>
</form>
<form action='/kaeri' method='get'>
<button type='submit'>Rückkehr</button>
</form>
</body>
</html>
.html:test2.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<title>Jikokuhyou</title>
<style>body{padding:10px;}</style>
</head>
<body>
{{'Der neueste Bus ist'+bustime}} <br>{{'Der nächste Bus ist'+next_bustime}}
<form action='/' method='get'>
<button type='submit'>Rückkehr</button>
</form>
</body>
</html>
.py:__init__.py
linebot_jikokuhyou
├csv_kakou.py
├csv_to_sql.py
├local_main.py
├jikoku_main.py
├main.py (zusätzlich)
├requirments.txt (zusätzlich)
├runtime.txt (zusätzlich)
├Procfile (zusätzlich)
├assets
│ ├database.py
│ ├models.py
│ ├data.db (bisher erstellte Dateien)
│ ├__ini__.py
│ ├jikoku.csv (bisher erstellte Dateien)
│ ├iki.csv
│ └kaeri.csv
│
└templates
├test.html
└test2.html
.py:main.py
from flask import Flask, request, abort
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,LocationMessage,ImageSendMessage
)
import os
import jikoku_main as jm
app = Flask(__name__)
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
@app.route("/")
def hello_world():
return "hello world!"
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
if 'Gehen' in event.message.text:
result1,result2 = jm.jikoku_search('Gehen')
line_bot_api.reply_message(
event.reply_token,
[
ImageSendMessage(original_content_url='https://www.photolibrary.jp/mhd5/img237/450-2012011014412960119.jpg',
preview_image_url='https://www.photolibrary.jp/mhd5/img237/450-2012011014412960119.jpg'),
TextSendMessage(text=result1),
TextSendMessage(text=result2)
]
)
if 'Rückkehr' in event.message.text:
result1,result2 = jm.jikoku_search('Rückkehr')
line_bot_api.reply_message(
event.reply_token,
[
ImageSendMessage
(original_content_url='https://www.photolibrary.jp/mhd5/img237/450-2012011014412960119.jpg',
preview_image_url='https://www.photolibrary.jp/mhd5/img237/450-2012011014412960119.jpg'),
TextSendMessage(text=result1),
TextSendMessage(text=result2)
]
)
if __name__ == "__main__":
port = int(os.getenv("PORT", 5000))
app.run(host="0.0.0.0", port=port)
・ Die Gesamtstruktur von LINE Bot finden Sie unter Verwenden wir LINE BOT (CallBack-Programm: Empfang). Es war.
-Modifizieren Sie database.py, wenn Sie Herokus postgresql verwenden.
.py:database.py
#coding: utf-8
#database.py/Datei, die die anfänglichen Einstellungen der zu verwendenden Datenbank verarbeitet, z. B. SQLite
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session,sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import datetime
import os
#data_Benannt db, Datenbank.Wo py ist (os.path.dirname(__file__)), Mit einem absoluten Pfad (os.path.abspath)、data_Speichern Sie die Datenbank Speichern Sie den Pfad.
database_file = os.path.join(os.path.abspath(os.path.dirname(__file__)),'data.db')
#Verwenden der Datenbank sqlite (engin)、database_Daten in Datei gespeichert_Verwenden Sie db und geben Sie sqlite aus, wenn Sie mit echo (echo) arbeiten=True)
#engine = create_engine('sqlite:///' + database_file,convert_unicode=True,echo=True)
engine = create_engine(os.environ.get('DATABASE_URL') or 'sqlite:///' + database_file,convert_unicode=True,echo=True)
db_session = scoped_session(
sessionmaker(
autocommit = False,
autoflush = False,
bind = engine
)
)
#declarative_Erstellen Sie eine Instanz von base
Base = declarative_base()
Base.query = db_session.query_property()
#Funktion zum Initialisieren der Datenbank
def init_db():
#Importieren Sie Modelle in den Assets-Ordner
import assets.models
Base.metadata.create_all(bind=engine)
・ Greifen Sie zuerst auf LINE Develpers zu, registrieren Sie sich und erstellen Sie einen neuen Kanal (Erklärung wird weggelassen).
heroku config:set YOUR_CHANNEL_ACCESS_TOKEN="Kanalzugriffstoken-Zeichenfolge" -a (App-Name)
heroku config:set YOUR_CHANNEL_SECRET="Geheime Zeichenfolge des Kanals" -a (App-Name)
Stellen Sie sicher, dass die Umgebungsvariablen in Heroku richtig eingestellt sind.
heroku config
-Erstellen Sie Procfile, runtime.txt, require.txt.
.txt:runtime.txt
python-3.8.2
web: python main.py
Beschreiben Sie die Datei "resources.txt", indem Sie im Terminal Folgendes eingeben.
pip freeze > requirements.txt
git add .
git commit -m'the-first'
git push heroku master
Heroku open
↓ ↓ ↓ ↓ ↓ Heroku öffnen und mit einem Browser überprüfen. Wenn "Hallo Welt!" Angezeigt wird, ist die Bereitstellung erfolgreich abgeschlossen.
Stellen Sie die Heroku-Datenbank postgresql ein und schreiben Sie CSV-Daten in die Datenbank. -Setze postgresql aus der Ressource der Heroku-App.
Führen Sie den Befehl bash aus, damit der Befehl in die Heroku-Umgebung eingegeben werden kann.
Führen Sie anschließend csv_to_sql.py aus.
Auf diese Weise wird postgresql initialisiert und CSV-Daten werden in postgresql geschrieben.
heroku run bash
python3 csv_to_sql.py
Stellen Sie sicher, dass es richtig geschrieben ist. Geben Sie den folgenden Befehl ein.
heroku pg:psql
Befehl zum Auflisten der Daten in der Tabelle
select *von (Tabellenname);
Ich konnte bestätigen, dass Folgendes ausgegeben wurde und dass es ordnungsgemäß in postgresql geschrieben wurde.
Legen Sie die URL für den Webhook von LINE Developers fest und aktivieren Sie die Verwendung des Webhooks (Details werden weggelassen). Registrieren Sie sich als Freund und starten Sie LINE Bot, um den Vorgang abzuschließen.