[PYTHON] Zeigen Sie Disneys Wartezeit mit dem LINE-Bot an

Inhaltsverzeichnis

** Fett ** ist, wo ich es schwer hatte

Überblick

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.

Erstellt LINE Bot

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).

Verzeichnisaufbau

Diagramm

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

Einführung jeder Datei

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

Ablauf des Betriebs

  1. Lassen Sie die Home-Taste drücken (reichhaltiges Menü unten beschrieben).
  2. Parkauswahl
  3. Eröffnungsprüfung
  4. Wenn der Park geöffnet ist, wählen Sie die Kategorie der Wartezeit aus, die Sie erhalten möchten (reichhaltiges Menü wird später beschrieben).
  5. Scraping → Ausgabe mit Flex Message-Rezept

Ein reichhaltiges Menü erstellen

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.

Parkauswahl (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
)

JSON-Dateien anzeigen

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.

  1. Erstellen Sie eine JSON-Datei

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.

Wichtig!

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.

  1. Ersetzen Sie im folgenden Code Ersetzen Sie im Zeichenfolgenteil.

    template = template_env.get_template('theme_select.json')
    
  2. 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))
            )

Unterschied zwischen Push und Antwort

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))
    )
) 

Eröffnungsscheck

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.

Wählen Sie die Wartezeitkategorie aus, die Sie erhalten möchten, wenn der Park geöffnet ist

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.

Scraping → Ausgabe mit Flex Message-Rezept

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": [
            
        ]
        }
    ]
    }
}

Variablen teilweise einbetten

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

  1. Lesen Sie zuerst die obige JSON-Datei in beschreibbarer Form
  2. Gehen Sie so weit wie "Text": "Thema", indem Sie die Elemente der komplexen Liste angeben (möglicherweise in einigen Editoren leicht zu finden).
  3. Und wenn Sie dem Inhalt von "Text" eine Variable zuweisen, können Sie einem Teil eine Variable zuweisen. Es ist wie es ist.

Betten Sie Elemente ein, die sich von Zeit zu Zeit ändern

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.

Dateiinitialisierung

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.

Zusammenfassung und zukünftige Ausgaben

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

Zeigen Sie Disneys Wartezeit mit dem LINE-Bot an
Überwachen Sie Webseitenaktualisierungen mit LINE BOT
Ich habe einen Stempelersatzbot mit Linie gemacht
Erstellen Sie mit Minette für Python einen LINE BOT
LINE BOT mit Python + AWS Lambda + API Gateway
Ich habe einen LINE Bot mit Serverless Framework erstellt!
Serverloser LINE-Bot mit IBM Cloud-Funktionen
Erstellen Sie mit Amazon Lex einen LINE WORKS-Bot
[AWS] Ich habe BOT mit LINE WORKS daran erinnert
Ich habe mit LINE Bot ein Haushaltsbuch für Bot erstellt
Machen Sie mit LINE + Flask einen morphologischen Analyse-Bot
Zeigen Sie die Zeilennummer des VIM-Editors an (mit Standardeinstellungen).
Ich habe versucht, LINE BOT mit Python und Heroku zu machen
[Super einfach] Machen wir einen LINE BOT mit Python.
[LINE Messaging API] Erstellen Sie einen Papageienrückgabe-BOT mit Python
Machen Sie einen LINE BOT
LINE BOT, wenn ~ gestolpert ist
Taskleistenanzeige mit tqdm
TOPIX-Zeitreihen anzeigen
Erstellen Sie mit GoogleAppEngine / py einen LINE-Bot. Einfache nackte Version
Erstellen Sie eine App für maschinelles Lernen mit ABEJA Platform + LINE Bot
Lassen Sie uns den Befehl pünktlich mit dem Bot der Zwietracht ausführen
Bis Django etwas mit einem Linienbot zurückgibt!
[AWS] Ich habe BOT mit LINE WORKS (Implementierung) in Erinnerung gerufen.