So erstellen Sie einen Chat-Bot für VKontakte mit Python, Django und Webhook

Warum noch ein Artikel zum Erstellen eines Chat-Bot?


Vielleicht sah ich schlecht aus, aber ich konnte keine detaillierte Anleitung zum Erstellen eines Python-Bot mithilfe des Django-Frameworks und des Webhook-Ansatzes finden, der von einem russischen Unternehmen gehostet wird. Die meisten Materialien sprechen über die Verwendung des Flask-Frameworks und die Verwendung von kostenlosen Heroku- und PythonAnywhere-Hosting-Sites. Die Erfahrung der Habr-Gemeinschaft hilft mir, deshalb entschied ich mich, diesen Artikel aus Dankbarkeit zu schreiben. Ich werde die gesammelten praktischen Erfahrungen beschreiben, damit alle, die daran interessiert sind, Zeit sparen und besser verstehen können, wie ein Python-Bot mithilfe des Django-Frameworks in Ihrem Hosting mithilfe des Webhook-Ansatzes erstellt wird.

Warum kostenpflichtiges Hosting?


Meiner Meinung nach ist eine funktionsfähige Version des Bots, wenn er nicht von Ihrem lokalen Computer abhängt und rund um die Uhr verfügbar ist. Dazu benötigen Sie ein Hosting, auf dem sich Folgendes befindet: ein Webserver, ein Datenbankverwaltungssystem (zur Entwicklung der Fähigkeiten des Bots), eine Domänennamenregistrierung, ein SSL-Zertifikat dafür und technischer Support für die gesamte Farm. Solche Dienstleistungen kosten Geld. Das Hosting zahle 138 Rubel pro Monat für die Aufrechterhaltung der Infrastruktur für den Bot-Betrieb: Python + Django-Unterstützung, MySQL 25 GB DBMS, SSH-Unterstützung.
In den meisten Lektionen habe ich gesehen, dass ein PC als Server oder kostenloses Hosting mit begrenzter Zeit verwendet wird. In den Beispielen fragt der Bot den Messenger-Server regelmäßig nach neuen Nachrichten von Benutzern ab. Dies ist eine zusätzliche Belastung der Messenger-Server, sodass der Bot für eine Weile "verbieten" kann. All dies ist meiner Meinung nach nicht entscheidend für den produktiven Einsatz. Aber für den Test ist das Training durchaus möglich.

Was ist Webhook und warum?


Um produktiv zu sein, halte ich die richtige Lösung für die Verwendung eines Webhooks für sinnvoll, d. H. Einen Ansatz, bei dem unser Bot Nachrichten vom Messenger-Server erwartet, anstatt ihn mit periodischen Abfragen zu "hämmern": Gibt es neue Nachrichten oder nicht? Bei Webhook wird es so aussehen: Der Benutzer hat eine Nachricht geschrieben, der Messenger-Server hat sie an Ihren Bot gesendet, er hat die Nachricht erhalten, sie verarbeitet und beantwortet.

Warum Django?


Ich beschloss, einen Bot in Python zu erstellen, also verband ich Python-Support mit dem Hosting. Aber ich hatte keine Wahl für das Framework - Hosting hat nur Django. Sie sagen, es laufen Instagram, Pinterest, Bitbucket und Mozilla. Vielleicht bietet Hosting deshalb genau das an.

Warum VKontakte, nicht Telegramm oder Viber?


Um von einfach zu komplex zu wechseln, war es mir wichtig, den einfachsten und verständlichsten Weg zu finden, einen Webhook einzurichten. VKontakte war für mich am verständlichsten, da der Webhook im Community-Steuerungsfeld im Abschnitt "Verwaltung - Arbeiten mit API" eindeutig und einfach zu verbinden ist. Als nächstes wird beschrieben, wie ich alles eingerichtet und verbunden habe. In Zukunft möchte ich meinen Bot in Viber verfügbar machen. Und mit Telegram ist noch nicht unterwegs, seit meinem Hosting in Russland, und aus Russland ist Telegram gesperrt. Um Probleme mit Telegram zu vermeiden, können Sie das Hosting im Ausland kaufen.

Wie installiere ich den Webhook für den VK-Bot?


Domainname https: // . Zuerst müssen Sie den Domainnamen der Site registrieren und ein SSL-Zertifikat dafür anfordern.

Ich wollte die Stammdomäne nicht für den Chat-Bot verwenden. Nach der Registrierung der Domäne erstellte ich eine Unterdomäne und erhielt ein SSL-Zertifikat dafür.

Ich habe alle diese Manipulationen an der Website vorgenommen, die in meinem persönlichen Konto gehostet wird.
Als Ergebnis erhielt ich die Adresse der Website mybot.mysite.ru und das SSL-Zertifikat dazu.

Wir erhalten für Bot Bot Access Key (Token) VKontakte. Zuerst habe ich eine geschlossene Gruppe erstellt, dann bin ich in die Gruppe "Management" gegangen, im Abschnitt "Arbeiten mit API". Auf der Registerkarte "Access Keys" befindet sich ein Token und auf der Registerkarte "Callback API" die Webhook-Einstellungen.



Installieren und konfigurieren Sie Django. Vielleicht ist es nicht nötig, Ihr Skript in Python Django auszuführen, aber ich weiß nicht, wie es anders möglich ist.

Mit PuTTY habe ich mich über SSH mit dem Server verbunden, eine virtuelle Umgebung eingerichtet und aktiviert.

SSH:
virtualenv-2.7 virtualenv/myEnv
. virtualenv/myEnv/bin/activate

Der Befehl in der ersten Zeile erstellt eine virtuelle Umgebung, und der Befehl in der zweiten aktiviert diese (beachten Sie das Leerzeichen nach dem Punkt). Version 2.7 wird vom Hosting vorgegeben und kann in Ihrem Fall abweichen. Lesen Sie also die Hosting-Hilfe.

Als nächstes habe ich Django
SSH installiert :
pip install ‘django<2’

Ich habe die Django-Version nicht vor der zweiten installiert, da das Hosting Python 2.7 verwendet, und nur Django-Version mit weniger als 2 funktioniert.

Außerdem habe ich das Python-Modul installiert, um mit der VKontakte-
SSH- API zu arbeiten :
pip install vk


FTP: Es wurde
ein Ordner für Django-Projekte im Stammverzeichnis des Hosters erstellt. Nannte ihren Django.

SSH:
Erstellt ein neues Projekt.
cd django/
django-admin.py startproject mybot

Als Ergebnis wird ein Ordner mit dem Namen des Projekts (in unserem Fall "mybot") im Ordner / django erstellt. Es enthält die automatisch erstellten ursprünglichen Projektdateien:
/ django
 / mybot - Projektordner
  / mybot - Modul mit den Einstellungen unseres Projekts
    __init__.py
     settings.py
     urls.py
     wsgi.py
  manage.py Das

Projekt in Django ist eine Gruppe von Anwendungen. Eine Django-Anwendung ist ein Programm, das die vom Entwickler festgelegten Aktionen ausführt.

SSH:
Eine Anwendung wurde erstellt.
cd mybot
python manage.py startapp vk_bot

Ich zog in den Ordner / django / mybot um und erstellte eine neue Anwendung namens „vk_bot“.
Im Projektordner wurde ein Ordner mit dem Namen der Anwendung erstellt, der die automatisch erstellten Anwendungsdateien enthält:

/ django
 / mybot - der Projektordner
  / mybot - das Modul mit unseren Projekteinstellungen
     __init__.py
     settings.py
     urls.py
     wsgi.py
  manage.py
  / vk_bot - Ordner
     __init__.py applications
     admin.py
     apps.py
     models.py
     tests.py
     views.py

FTP:
Ich habe alle Projektdateien auf meinen Laptop hochgeladen, um mit Code arbeiten zu können.
Um mit Projektdateien und der Programmierung zu arbeiten, habe ich die Atom-Anwendung verwendet.

Atom:
Bearbeitete Projekteinstellungen in der Datei /django/mybot/mybot/settings.py
...
DEBUG = False
...
ALLOWED_HOSTS = [
    u'mybot.mysite.ru',
]
...

Atom:
Bearbeitete URL-Adress-Routing-Einstellungen in der Datei /django/mybot/mybot/urls.py
...
urlpatterns = [
    url(r'^vk_bot/', include('vk_bot.urls')),
]
...

FTP:
Erstellt eine Datei /django/mybot/vk_bot/urls.py mit folgendem Inhalt:
from django.conf.urls import url
from . import views
app_name = 'vk_bot'
urlpatterns = [
    url(r'^$', views.index, name='index'),
]

Atom:
Die Datei /django/mybot/vk_bot/views.py wurde bearbeitet - eine Funktion namens index wurde hinzugefügt, die ausgeführt wird, wenn der Browser die Adresse anfordert
https://mybot.mysite.ru/vk_bot/


views.py
# -*- coding: utf-8 -*-from __future__ import unicode_literals
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
from django.http import HttpResponse
from bot_config import * # import token, confirmation_token and over constants from bot_config.pyimport json, vk # vk is library from VK"""
Using VK Callback API version 5.5
For more ditalies visit https://vk.com/dev/callback_api
""""""
From Django documentation (https://docs.djangoproject.com/en/1.11/ref/request-response/)
When a page is requested, Django automatically creates an HttpRequest object that contains
metadata about the request. Then Django loads the appropriate view, passing the
HttpRequest as the first argument to the view function.
This argiment is <request> in def index(request):
Decorator <@csrf_exempt> marks a view as being exempt from the protection
ensured by the Django middleware.
For cross site request protection will be used secret key from VK
"""@csrf_exempt #exempt index() function from built-in Django protectiondefindex(request):#url: https://mybot.mysite.ru/vk_bot/if (request.method == "POST"):
        data = json.loads(request.body)# take POST request from auto-generated variable <request.body> in json formatif (data['secret'] == secret_key):# if json request contain secret key and it's equal my secret keyif (data['type'] == 'confirmation'):# if VK server request confirmation"""
                For confirmation my server (webhook) it must return
                confirmation token, whitch issuing in administration web-panel
                your public group in vk.com.
                Using <content_type="text/plain"> in HttpResponse function allows you
                response only plain text, without any format symbols.
                Parametr <status=200> response to VK server as VK want.
                """# confirmation_token from bot_config.pyreturn HttpResponse(confirmation_token, content_type="text/plain", status=200)
            if (data['type'] == 'message_new'):# if VK server send a message
                session = vk.Session()
                api = vk.API(session, v=5.5)
                user_id = data['object']['user_id']
                # token from bot_config.py
                api.messages.send(access_token = token, user_id = str(user_id), message = "Hello, I'm bot!")
                return HttpResponse('ok', content_type="text/plain", status=200)
    else:
        return HttpResponse('see you :)')

Im view.py- Skript , in der Index- (Anforderungs-) Funktion, musste ich den integrierten Schutz in Django CSRF deaktivieren, da Ich habe die Fehlermeldung "403 Forbidden" erhalten. CSRF - Cross Site Request-Fälschungsschutz - Standortübergreifender Request-Fälschungsschutz. Wie CSRF funktioniert, lesen Sie in diesem Artikel .
Um den Schutz zu deaktivieren, habe ich den Dekorator @csrf_exempt verwendet . Um diesen Schutz dennoch zu gewährleisten, habe ich auf einfachere Weise den geheimen Schlüssel verwendet, der in der Gruppenverwaltung auf der VKontakte-Site vorgeschrieben ist.

Dieser Code ist für die Verarbeitung von Anforderungen vom Server verantwortlich, die er an den Webhook zur Verarbeitung von Ereignissen sendet. Sagen wir einfach "Bestätigung" unseres Webhook'a.
if (data['type'] == 'confirmation'):# if VK server request confirmation"""
    For confirmation my server (webhook) it must return
    confirmation token, whitch issuing in administration web-panel
    your public group in vk.com.
    Using <content_type="text/plain"> in HttpResponse function allows you
    response only plain text, without any format symbols.
    Parametr <status=200> response to VK server as VK want.
    """# confirmation_token from bot_config.pyreturn HttpResponse(confirmation_token, content_type="text/plain", status=200)

Bitte beachte, dass ich alle Konfigurationseinstellungen in der Bot-Konfigurationsdatei bot_config.py belege und sie daher am Anfang des Skripts verbinde:
from bot_config import * # import token, confirmation_token and over constants from bot_config.py

bot_config.py
# -*- coding: utf-8 -*-"""
Configuration file for VK bot
"""# token issued on the VK group web-administration page
token = '...'# confirmation token issued on the VK group web-administration page in "Callback API" section
confirmation_token = '...'# secret key for cross site request forgery protection. It will be in each VK server request
secret_key = '...'

In diesem Code werden die Nachrichten der Benutzer verarbeitet:
if (data['type'] == 'message_new'):# if VK server send a message
    session = vk.Session()
    api = vk.API(session, v=5.5)
    user_id = data['object']['user_id']
    # token from bot_config.py
    api.messages.send(access_token = token, user_id = str(user_id), message = "Hello, I'm bot!")
    return HttpResponse('ok', content_type="text/plain", status=200)

Wenn etwas unverständlich schien, können Sie zusätzlich einen Artikel über das erste Setup von Django lesen .

Magie für den Webserver . So konfigurieren Sie Adressanforderungen an dem Web - Server auf einem Server in einem Ordner mit Domänen per FTP-Client FileZilla und erstellt dort einen Ordner „gegangen ist mybot.mysite.ru “, um es drei Dateien, dessen Inhalt aus dem Bericht über das Hosting gesetzt werden:

.htaccess
AddHandler wsgi-script .wsgi
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /django.wsgi/$1 [QSA,PT,L]
RewriteCond %{HTTP:X-Forwarded-Protocol} !=https
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

django.wsgi
import os, sys
virtual_env = os.path.expanduser('~/virtualenv/myEnv')
activate_this = os.path.join(virtual_env, 'bin/activate_this.py')
execfile(activate_this, dict(__file__=activate_this))
sys.path.insert(0, os.path.join(os.path.expanduser('~'), 'django/mybot'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'mybot.settings'from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

"MyEnv" ist der Name der von Ihnen erstellten virtuellen Umgebung, "django" ist der Ordner in der Root-Partition des Dateisystems auf dem Hosting, "mybot" ist der Name des Projekts, das mit Django erstellt wurde.

index.html
Сайт в разработке

Wir binden unseren Webhook an die Verarbeitung von Nachrichten in der erstellten Vkontakte-Gruppe.
Dazu kehren wir zum Management-Bereich unserer Gruppe auf der Website VKontakte zurück (siehe Abbildung oben). Geben Sie in das Feld "Adresse" unsere Adresse ein
https://mybot.mysite.ru/vk_bot/
und klicken Sie auf "Bestätigen". Wenn unser Funktionsindex (request) , der in die Datei /django/mybot/vk_bot/views.py geschrieben ist, ordnungsgemäß funktioniert, d. H. Keine Tippfehler oder Fehler, wird ein grünes Häkchen angezeigt , das anzeigt , dass alles in Ordnung ist.

Damit unser Webhook Nachrichten über neue Nachrichten vom VKontakte-Server erhalten kann, haken wir im Verwaltungsbereich unserer Gruppe auf der VKontakte-Website im Register "Ereignistypen" die "eingehenden Nachrichten" ab.

Als Ergebnis erhält unser Skript diese Nachrichten im Json- Format:

{"type":"message_new","object":{"id":891,"date":1541599508,"out":0,"user_id":1...1,"read_state":0,"title":"","body":"текст сообщения пользователя"},"group_id":1...4,"secret":"uxSBw"}

Beachten Sie, dass sich in der Json- Nachricht ein "geheimes" Feld befindet. Dies ist derselbe geheime Schlüssel, den ich im Gruppenverwaltungsabschnitt von VKontakte registriert habe, anstelle des in Django CSRF integrierten Schutzes, den ich deaktivieren musste.

Wie kann man den Bot intelligenter und besser machen?


Sie können eine Datenbank mit den Antworten des Benutzers erstellen und dem Bot beibringen, die Antwort auszuwählen, die der Frage des Benutzers am nächsten kommt. Ich werde darüber in einem separaten Artikel berichten.
Es ist möglich und notwendig, Benutzerinteraktionsskripts so zu programmieren, dass die Konversation unterstützt wird.

Erfolge in Ihrer kreativen Arbeit!

Jetzt auch beliebt: