** Fett ** ist, wo ich es schwer hatte
Ich habe einen Bot mit Python anstelle von node.js erstellt, indem ich auf die folgende Site verwiesen habe. Die durch Schaben erhaltenen Informationen wurden auch von derselben Stelle wie der oben aufgeführten erhalten.
Ich habe einen LINE-Bot erstellt, der mir die Wartezeit von Disney angibt
Da diese Site einfach zu bedienen sein soll, gibt es viele Zeichenfolgen. Im Gegenteil, wir haben umfangreiche Menüs und Flex Message verwendet, damit Benutzer die gewünschten Daten auswählen können. Reichhaltige Menüs, Flex-Nachrichten usw. sind nicht organisiert, daher habe ich mir die Referenzen angesehen und zwischen verschiedenen Websites hin und her gewechselt. Ich hoffe, sie auch zusammenfassen zu können.
Ich werde zuerst die fertige Version einfügen. Bitte registrieren Sie sich und nutzen Sie es, wenn Sie möchten! Um direkt zu lesen, bitte hier klicken
Der Quellcode ist auf GitHub verfügbar. Wenn Sie weitere Details wie Scraping-Code anzeigen möchten, klicken Sie bitte hier (https://github.com/ryodisney/disney_wait).
Ich habe alles in einen Ordner namens Disney gelegt. Da .git eine versteckte Datei war, wird sie hier nicht angezeigt, befindet sich jedoch in derselben Hierarchie wie deploy.bat.
disney
├ deploy.bat
├ main.py
├ scrape_requests.py
├ makejsonfile.py
├ Procfile
├ runtime.txt
├ requirements.txt
│
└─templates
land_theme.json
recipt.json
sea_theme.json
theme_select.json
Der Teil, der den LINE-Bot bewegt, wird später erläutert, sodass der Inhalt der Einstellungsdatei unten aufgeführt ist.
** deploy.bat **: Dies erspart Ihnen die Eingabe jedes Befehls, wenn Sie eine geänderte Version auf Heroku verschieben.
deploy.bat
git add . && git commit -m 'Improve' && git push
** Procfile **: Erstellt eine Procfile, eine Konfigurationsdatei, die Heroku das Starten des Programms beibringt. Geben Sie den folgenden Befehl ein, nachdem Sie an der Eingabeaufforderung in das aktuelle Verzeichnis gewechselt sind. Setzen Sie zu diesem Zeitpunkt diejenige, die zuerst beginnt, an die Stelle, an der main.py geschrieben ist. Der Name muss nicht main.py sein.
Procfile
echo web: python main.py > Procfile
** runtime.txt **: Die zu verwendende Version von Python ist hier aufgelistet.
runtime.txt
python-3.7.0
** Anforderungen.txt **: Hier wird die Pip-Installation der in Python verwendeten Module geschrieben. Jetzt können Sie diese Module auch auf der Heroku-Seite verwenden.
requirements.txt
Flask==1.1.1
line-bot-sdk==1.15.0
requests==2.21.0
bs4==0.0.1
lxml==4.4.2
https://github.com/heroku/heroku-buildpack-chromedriver.git
https://github.com/heroku/heroku-buildpack-google-chrome.git
Der im Bild unten gezeigte 6-teilige Teil ist das reichhaltige Menü. Dieses Mal werde ich es nicht selbst erstellen, sondern die Funktionen von LINE Official Manager verwenden. Ich wollte wirklich Postback verwenden, also wollte ich es komplett selbst machen, aber ich habe Kompromisse geschlossen, weil ich selbst nach dem Lesen der Referenz nicht verstanden habe, wie man es implementiert.
LINE Official Manager Klicken Sie nach dem Anmelden auf den roten Rahmen unten. Wenn Sie dort auf die Schaltfläche Erstellen klicken, wird die folgende Seite angezeigt. Der Titel kann alles sein. Es scheint zu unterscheiden, wenn Sie mehrere reichhaltige Menüs erstellen. (Es scheint, dass Sie das Rich-Menü nicht mit demselben Konto wechseln können, wenn Sie es nicht selbst erstellen.) Ich denke, dass die Anzeigezeit länger beiseite gelegt werden sollte. Das Startdatum wird erst bekannt gegeben, wenn es vor dem Implementierungsdatum liegt. (Natürlich)
Gehen Sie zu ** Inhaltseinstellungen **. Sie können die Anzahl der Unterteilungen auswählen, indem Sie ** Vorlage auswählen ** drücken. Ich habe hier 6 Abteilungen ausgewählt. Wenn Sie ** Hintergrundbild hochladen ** auswählen, handelt es sich um ein einseitiges Bild. Wenn Sie also ein Bild einzeln an 6 Bereiche anhängen möchten, drücken Sie unten ** Bild erstellen **. Sie können die Reaktion auch auswählen, wenn Sie sie mit einer Aktion drücken. Dieses Mal wird es zu dem Ereignis danach führen, also werde ich es zu einem Text machen. (Ich glaube nicht, dass ich viele Möglichkeiten habe, andere zu nutzen) Hier sind einige Punkte beim Erstellen eines Bildes. Zunächst können Sie das Bild hochladen, indem Sie auf das rote Kreissymbol klicken. Und der äußere Rahmen wird vom blauen Kreissymbol eingerahmt. Ich denke, es wäre besser, wenn wir die Grenzen ohne dies nicht verstehen könnten. Bei der Standarddicke gab es eine Lücke, sodass die Kante mit maximal 5 genau richtig war. Drücken Sie außerdem in der oberen rechten Ecke auf ** Übernehmen **. Wenn Sie es in der Mitte drücken, wird es als einzelnes Bild im Hintergrund gespeichert und Sie können es nicht einzeln bearbeiten. Dieses reichhaltige Menü ist das Ergebnis.
Die im Betriebsablauf geschriebene Home-Taste ist das Mickey-Symbol in der unteren Mitte. Es ist dafür verantwortlich, den Text "Home" zurückzugeben, wenn es gedrückt wird. Die anderen fünf dienen alle zur Auswahl einer Kategorie, unterscheiden sich also von der Home-Schaltfläche.
Nach dem Drücken der Home-Taste wird eine Schaltfläche wie die folgende angezeigt, mit der Sie einen Park auswählen können. Ich werde die Verarbeitung grob beschreiben, wenn die Home-Taste gedrückt wird. Danach gibt es ein Post-Back-Ereignis und es gibt Informationen, die ich speichern möchte, z. B. welcher Park ausgewählt ist. Daher verwende ich globale Variablen unter Berücksichtigung des Umfangs der Variablen. Der Vorgang nach dem Drücken der Home-Taste beginnt mit ** les = "les" **. Die wichtigen Punkte sind die folgenden zwei Punkte.
home_button.py
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
global park,genre,area,info_url,target_url,counter,situation
text = event.message.text
userid = event.source.user_id
#Zuerst und zurücksetzen
if text == "Zuhause":
#Initialisieren
park = "park"
genre = "genre"
area = "area"
info_url = ""
target_url = ""
counter = 0
situation = ""
les = "les"
template = template_env.get_template('theme_select.json')
data = template.render(dict(items=les))
select__theme_massage = FlexSendMessage(
alt_text="Themenauswahl",
contents=BubbleContainer.new_from_json_dict(json.loads(data))
)
line_bot_api.push_message(userid, messages=select__theme_massage)
Das erste, worüber ich schreiben möchte, ist TextMessage und FlexSendMessage. Diese müssen oben im Quellcode manipuliert werden, der in parrot return kopiert und eingefügt wird. Es scheint, dass das Ereignis-, Aktions- und Nachrichtensystem wie unten gezeigt importiert werden muss. Wenn Sie eine Fehlermeldung erhalten, überprüfen Sie bitte, ob diese hier beschrieben ist.
from linebot.models import (
MessageEvent, TextMessage, PostbackTemplateAction, PostbackEvent, PostbackAction, QuickReplyButton, QuickReply,
FlexSendMessage, BubbleContainer, CarouselContainer, TextSendMessage
)
Um ehrlich zu sein, weiß ich nur, wie ich es mit jinja2 auf die Vorlage anwenden kann, daher verstehe ich nicht viel. Wenn Sie ein Anfänger sind, ist es daher schneller, ** les = "les" ** oder weniger zu kopieren.
Ich habe Flex Message Simulator verwendet, um mit dem fertigen Produkt zu spielen und es vorerst in Form zu bringen.
```json:theme_select.json
{
"type": "bubble",
"hero": {
"type": "image",
"url": "https://secured.disney.co.jp/content/disney/jp/secured/dcc/tokuten/bf-tdr-prk-tckt/_jcr_content/par/dcc_hero_panel_image/image1.img.jpg/1474355301452.jpg ",
"size": "full",
"aspectRatio": "20:13",
"aspectMode": "cover"
},
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "Bitte wählen Sie einen Park",
"weight": "bold",
"size": "lg"
}
]
},
"footer": {
"type": "box",
"layout": "vertical",
"spacing": "sm",
"contents": [
{
"type": "button",
"style": "link",
"height": "sm",
"action": {
"type": "postback",
"label": "Land",
"data": "land"
}
},
{
"type": "button",
"style": "link",
"height": "sm",
"action": {
"type": "postback",
"label": "C.",
"data": "sea"
}
},
{
"type": "spacer",
"size": "sm"
}
],
"flex": 0
}
} ``` Der Inhalt von "Aktion" ist - type - label - data
"Typ" ist die Form des Datenaustauschs, "Beschriftung" steht auf der Schaltfläche (in diesem Fall "Land", "Meer") und "Daten" sind die zu empfangenden Daten. Es scheint, dass Bilder und Töne auch in "Daten" enthalten sind. Weitere Informationen finden Sie unter Referenz. (Ergänzung) Wählen Sie "Typ" von "Aktion": {} entsprechend dem Zweck. Wenn Sie möchten, dass es als Nachricht angezeigt wird, wenn der andere Teilnehmer darauf drückt, sollten Sie "type": message verwenden.
Um die JSON-Datei zu speichern, erstellen Sie einen Ordner namens Templates in derselben Hierarchie und speichern Sie ihn in diesem Ordner! Es scheint, dass es von dort liest.
Ersetzen Sie im folgenden Code Ersetzen Sie im Zeichenfolgenteil.
template = template_env.get_template('theme_select.json')
Wenn Sie ein Karussell implementieren (horizontale Folie 1), ändern Sie den folgenden Code Wechseln Sie vom Blasenbehälter zum Karussellbehälter.
select__theme_massage = FlexSendMessage(
alt_text="Themenauswahl",
contents=CarouselContainer.new_from_json_dict(json.loads(data))
)
Sie können für ein Ereignis mehrmals pushen, aber eine Antwort scheint nur einmal möglich zu sein. Wenn Sie also antworten, können Sie danach keine weiteren Nachrichten mehr senden. Angenommen, das Scraping dauert einige Zeit, wenn Sie beim Empfang einer Nachricht vom Benutzer "Verarbeitung" anzeigen und dann das Ergebnis in einer JSON-Datei anzeigen möchten, klicken Sie auf "Verarbeitung" und dann auf die JSON-Datei. Es wird durch Antworten gelöst. Außerdem muss push die Benutzer-ID und die Nachricht vorbereiten. Schauen Sie oben auf button.py und ahmen Sie es nach.
push.py
line_bot_api.push_message(userid, messages=select__theme_massage)
reply.py
line_bot_api.reply_message(
event.reply_token,
FlexSendMessage(
alt_text="Ergebnisanzeige",
contents=BubbleContainer.new_from_json_dict(json.loads(data))
)
)
Die Datums- und Uhrzeitangabe wird verwendet, um "geschlossen" mit Ausnahme der Öffnungszeiten anzuzeigen. Unten sind die beiden Codes. Die erste besteht darin, die Parkauswahldaten in einem Postback zu erhalten, die Geschäftszeiten zu überprüfen und dem Benutzer mit dem Rückgabewert zu antworten. Der zweite ist ein Code, der die Geschäftszeiten bestätigt. (Bonus)
** Hinweis: ** Wenn Herokus Zeitzone nicht auf Japan eingestellt ist, ist datetime die US-Zeitzone. Zur Zeitzoneneinstellung → dieser Artikel
postback_park.py
@handler.add(PostbackEvent)
def handle_postback(event):
global park,genre,area,info_url,target_url,counter,situation
area = ""
post_data = event.postback.data
userid = event.source.user_id
if post_data == "land" or post_data == "sea":
park = post_data
if park == "land":
#Links wie Öffnungszeiten und Wetter
info_url = "https://tokyodisneyresort.info/index.php?park=land"
park_ja = "Land"
elif park == "sea":
#Links wie Öffnungszeiten und Wetter
info_url = "https://tokyodisneyresort.info/index.php?park=sea"
park_ja ="C."
#Überprüfen Sie die Öffnungszeiten
business_hour = Scrape_day(info_url)
situation = Check_park(business_hour)
if situation == "close":
print("close")
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Der Park ist geschlossen")
)
elif situation == "open":
park_message = TextSendMessage(text= str(park_ja) + "Ist ausgewählt\n Kategorien aus dem Menü unten\n Bitte auswählen")
line_bot_api.push_message(userid, messages=park_message)
Das Leeren des Bereichs ist eine Fehlervermeidung, vorausgesetzt, Sie drücken versehentlich mehrmals die Taste.
check_park.py
#Überprüfen Sie, ob es jetzt Öffnungszeit ist
def Check_park(business_hour):
#Überprüfen Sie die aktuelle Uhrzeit und das aktuelle Datum
dt_now = dt.now()
#Heutiges Datum
year = int(dt_now.year)
month = int(dt_now.month)
day = int(dt_now.day)
#Aufteilung der Öffnungszeiten
open_time = business_hour.split("~")[0]
if open_time.split(":")[0] == "":
return "close"
else:
open_hour = int(open_time.split(":")[0])
open_minute = int(open_time.split(":")[1])
#Aufteilung der Schließzeit
close_time = business_hour.split("~")[1]
close_hour = int(close_time.split(":")[0])
close_minute = int(close_time.split(":")[1])
#Terminzeit
open_datetime = dt(year,month,day,open_hour,open_minute)
close_datetime = dt(year,month,day,close_hour,close_minute)
if open_datetime < dt_now < close_datetime:
return "open"
else:
return "close"
Das Argument business_hour ist eine Folge von Geschäftszeiten, die von der Site entfernt wurden.
Fahren Sie nach Auswahl des Parks mit dem nächsten Schritt fort, falls dieser geöffnet ist. Drücken Sie auf das soeben erstellte Rich-Menü und wählen Sie die Kategorie aus, in der die Latenz angezeigt werden soll. Zu diesem Zeitpunkt wird die ausgewählte Kategorie als Text auf dem Bildschirm angezeigt. Die einzige Möglichkeit, dies zu vermeiden, besteht darin, ein eigenes reichhaltiges Menü zu erstellen.
Wie oben erwähnt, wird der gesamte Code auf Github veröffentlicht, daher werde ich nichts über Latenz-Scraping schreiben. In diesem Abschnitt wird beschrieben, wie Sie das Rezept von Flex Message bei der Ausgabe des erfassten Werts verwenden. Wenn die Anzahl der auszugebenden Zeichenfolgen gering ist oder Sie sich nicht für die Form interessieren, ist der oben beschriebene Push oder die Antwort ausreichend, sodass Sie hier überspringen können.
Ich werde auch dieses Mal mit der JSON-Datei spielen, aber ich werde drei Hauptaufgaben erledigen.
Ich habe das Rezept von Flex Message Simulator bearbeitet und die folgende JSON-Datei erstellt.
recipt.json
{
"type": "bubble",
"styles": {
"footer": {
"separator": true
}
},
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "Wartezeit",
"weight": "bold",
"color": "#1DB446",
"size": "sm"
},
{
"type": "text",
"text": "Thema",
"weight": "bold",
"size": "xl",
"margin": "md"
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "vertical",
"margin": "xxl",
"spacing": "sm",
"contents": [
]
}
]
}
}
Ich möchte den Teil, in dem "Text": "Thema" geschrieben ist, in "Text": "erworbenes Zeichen" ändern. Führen Sie daher die folgende Verarbeitung durch.
set_json.py
def Send_area(area):
json_file = open('templates/recipt.json', 'r',encoding="utf-8-sig")
json_object = json.load(json_file)
json_object["body"]["contents"][1]["text"] = str(area)
#Schreiben
new_json_file = open('templates/recipt.json', 'w',encoding="utf-8")
json.dump(json_object, new_json_file, indent=2,ensure_ascii=False)
Als Prozedur
Dies wurde gelöst, indem eine Variable in eine Box mit fester Form eingebettet und zusätzlich eingefügt wurde.
new_json.py
def Make_jsonfile(attraction,info):
json_file = open('templates/recipt.json', 'r',encoding="utf-8-sig")
json_object = json.load(json_file)
new = {
"type": "box",
"layout": "vertical",
"margin": "xxl",
"spacing": "sm",
"contents": [
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": str(attraction),
"size": "sm",
"color": "#555555",
"flex": 0
},
{
"type": "text",
"text": str(info),
"size": "md",
"color": "#111111",
"align": "end"
}
]
}
]
}
json_object["body"]["contents"][3]["contents"].append(new)
new_json_file = open('templates/recipt.json', 'w',encoding="utf-8")
json.dump(json_object, new_json_file, indent=2,ensure_ascii=False)
Ich denke, es ist schwer zu verstehen, weil es kompliziert ist, aber das Wichtigste ist, dass wir anhängen (neu). Der leere Inhalt am Ende des obigen Rezepts.json ist im Listenformat, sodass Sie antworten können, indem Sie dort anhängen, auch wenn Sie die Anzahl der anzuzeigenden Daten nicht im Voraus kennen. In new_json.py sind der Name der Attraktion und die Wartezeit in Variablen eingebettet, und ein Feld, das sie zusammenfasst, wird in den Inhalt eingefügt.
Der Grund, warum die Codierung mit utf-8-sig erfolgt, besteht darin, Fehler zu vermeiden. Wenn Sie einen Fehler mit utf-8 haben, lesen Sie bitte diese Site → UnicodeDecodeError: When'cp932'appears
Wenn Herokus Protokollprüfung leer sagt, denke ich, dass dies die Ursache ist. Da der ursprüngliche Inhalt leer ist, wird beim Drucken eine Fehlermeldung angezeigt, wenn nichts hinzugefügt wurde. Lassen Sie uns zunächst überprüfen, ob dem Inhalt ein Kontrollkästchen hinzugefügt wurde.
Wenn Sie das Anhängen wiederholen, ohne es zu initialisieren, bleiben die bisherigen Informationen natürlich erhalten. Vor dem Erstellen des Rezepts wird es durch Überschreiben des obigen Rezepts initialisiert.
Obwohl es mein erster Beitrag war, ist er ziemlich lang geworden. Dieses Mal habe ich mich auf das reichhaltige Menü und die Flex-Nachricht konzentriert, die mir schwer gefallen haben, und ich hoffe, dass sie jemandem helfen werden. Die Herausforderungen, die aufgeworfen werden können, sind
es gibt. Insbesondere gibt es nur wenige Python-Artikel zum zweiten reichhaltigen Menü. Wenn also jemand, der diesen Artikel liest, damit vertraut ist, wäre ich Ihnen dankbar, wenn Sie ihn veröffentlichen könnten.
Recommended Posts