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

Warum noch ein Artikel zum Erstellen eines Chat-Bots?


Vielleicht habe ich schlecht gesucht, aber ich konnte keine detaillierte Anleitung zum Erstellen eines Python-Bots mit dem Django-Framework und dem Webhook-Ansatz finden, der von einer russischen Firma gehostet wird. In den meisten Materialien wird über die Verwendung des Flask-Frameworks und das kostenlose Hosting von Heroku und PythonAnywhere gesprochen. Die Erfahrung der Habr-Community hilft mir, und so habe ich mich aus Dankbarkeit entschlossen, Zeit damit zu verbringen, diesen Artikel zu schreiben. Ich werde die praktischen Erfahrungen beschreiben, die gesammelt wurden, damit jeder, der daran interessiert ist, Zeit sparen und besser verstehen kann, wie ein Bot in Python mithilfe des Django-Frameworks auf seinem Hosting mithilfe des Webhook-Ansatzes erstellt wird.

Warum kostenpflichtiges Hosting?


Meiner Meinung nach ist eine funktionsfähige Version des Bots, wenn er unabhängig von Ihrem lokalen Computer ist und rund um die Uhr verfügbar ist. Dazu benötigen Sie ein Hosting, auf dem sich Folgendes befindet: einen Webserver, ein Datenbankverwaltungssystem (um die Funktionen des Bots zu entwickeln), die Registrierung eines Domainnamens, das Erhalten eines SSL-Zertifikats und technischen Support für all diese Wirtschaftszweige. Solche Dienstleistungen kosten Geld. Ich bezahle das Hosting von 138 Rubel pro Monat für die Wartung der Infrastruktur, damit der Bot funktioniert: Unterstützung für Python + Django, MySQL DBMS 25 GB, Unterstützung für SSH.
In den meisten Lektionen habe ich gesehen, dass ein Personal Computer als Server oder kostenloses Hosting mit Einschränkungen der Arbeitszeit usw. 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 für die Messenger-Server, sodass der Bot für eine Weile "gesperrt" werden kann. All dies ist meiner Meinung nach für den produktiven Einsatz nicht entscheidend. Aber für den Test und das Training ist durchaus möglich.

Was ist Webhook und warum?


Für das Produkt halte ich die richtige Entscheidung für einen Webhook für richtig, dh einen Ansatz, bei dem unser Bot Nachrichten vom Messenger-Server erwartet und diese nicht mit regelmäßigen Anfragen „hämmert“: Gibt es neue Nachrichten oder nicht? Mit einem Webhook sieht es so aus: Der Benutzer hat eine Nachricht geschrieben, der Messenger-Server hat sie an Ihren Bot gesendet, er hat die Nachricht empfangen, verarbeitet und beantwortet.

Warum Django?


Ich habe beschlossen, einen Bot in Python zu erstellen, also habe ich die Python-Unterstützung auf dem Hosting angeschlossen. Aber ich hatte keine Wahl für ein Framework - Hosting hat nur Django. Sie sagen, es funktioniert Instagram, Pinterest, Bitbucket und Mozilla. Vielleicht bietet Hosting es deshalb an.

Warum VKontakte, nicht Telegramm oder Viber?


Um von einfach zu komplex zu wechseln, war es mir wichtig, den einfachsten und intuitivsten Weg zu finden, um einen Webhook einzurichten. VKontakte erwies sich für mich aufgrund der eindeutigen Hilfe und der einfachen Verbindung von Webhook im Community-Kontrollfeld im Abschnitt "Verwaltung - Arbeiten mit API" als am verständlichsten. Eine Beschreibung, wie ich alles konfiguriert und verbunden habe, wird weiter unten aufgeführt. In Zukunft möchte ich meinen Bot in Viber verfügbar machen. Aber mit Telegramm ist es noch nicht unterwegs, da mein Hosting in Russland ist und das Telegramm für Russland gesperrt ist. Um Probleme mit Telegramm zu vermeiden, können Sie Hosting im Ausland kaufen.

Wie installiere ich Webhook für VK Bot?


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

Ich wollte die Root-Domain nicht für den Chatbot verwenden, also habe ich nach der Registrierung der Domain eine Subdomain erstellt und ein SSL-Zertifikat dafür erhalten.

Ich habe all diese Manipulationen auf der Hosting-Site in meinem persönlichen Konto vorgenommen.
Als Ergebnis erhielt ich die Adresse der Site mybot.mysite.ru und das SSL-Zertifikat dafür.

Wir bekommen den VK-Schlüssel (Token) für den Bot. Zuerst habe ich eine geschlossene Gruppe erstellt und bin dann im Abschnitt "Arbeiten mit API" in die "Verwaltung" der Gruppe gegangen. Auf der Registerkarte "Access Keys" befindet sich ein Token und auf der Registerkarte "Callback API" die Webhook-Einstellungen.



Installieren und konfigurieren Sie Django . Vielleicht brauchen Sie Django nicht, um Ihr Python-Skript auszuführen, aber ich weiß nicht, wie es anders ist.

Mit PuTTY habe ich über SSH eine Verbindung zum Server hergestellt, die virtuelle Umgebung konfiguriert 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 Zeile aktiviert sie (beachten Sie das Leerzeichen nach dem Punkt). Version 2.7 wird vom Hosting vorgegeben und kann in Ihrem Fall abweichen. Lesen Sie daher die Hosting-Hilfe.

Als nächstes installierte Django
SSH:
 pip install 'django<2' 

Ich habe die Django-Version nicht früher als die zweite installiert, da Python 2.7 auf dem Hosting verwendet wird und nur die Django-Version unter 2 damit funktioniert.

Und installierte das Python-Modul, um mit der VKontakte-API zu arbeiten
SSH:
 pip install vk 


FTP:
Erstellt einen Ordner für Django-Projekte im Stammverzeichnis des Hostings. Er nannte sie Django.

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

Infolgedessen wird im Ordner / django ein Ordner mit dem Namen des Projekts erstellt (in unserem Fall „mybot“). Es enthält die ersten automatisch erstellten Projektdateien:
/ Django
/ mybot - Projektordner
/ mybot - Modul mit den Einstellungen unseres Projekts
__init__.py
settings.py
urls.py
wsgi.py
verwalten.py

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

SSH:
Erstellt eine Anwendung.
 cd mybot python manage.py startapp vk_bot 

Ich ging in den Ordner / django / mybot 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 - Projektordner
/ mybot - Modul mit den Einstellungen unseres Projekts
__init__.py
settings.py
urls.py
wsgi.py
verwalten.py
/ vk_bot - Anwendungsordner
__init__.py
admin.py.
apps.py
models.py
tests.py
views.py

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

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

Atom:
Bearbeitete URL-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. Es wurde eine Funktion namens index hinzugefügt, die ausgeführt wird, wenn die Adresse im Browser angefordert wird
  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.py import 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 protection def index(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 format if (data['secret'] == secret_key):# if json request contain secret key and it's equal my secret key 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.py return 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 Skript views.py musste ich in der Funktion index (request) den in Django CSRF integrierten Schutz deaktivieren, weil Ich habe den Fehler "403 Forbidden" erhalten. CSRF - Cross Site Request Forgery-Schutz - Schutz gegen Cross Site Request Forgery. Wie CSRF funktioniert, lesen Sie in diesem Artikel .
Um den Schutz zu deaktivieren, habe ich den Dekorator @csrf_exempt verwendet . Um diesen Schutz trotzdem zu gewährleisten, habe ich auf einfachere Weise einen geheimen Schlüssel verwendet, der im Bereich Gruppenverwaltung auf der VKontakte-Website registriert ist.

Dieser Code ist für die Verarbeitung von Anfragen vom Server verantwortlich, die gesendet werden, um unseren Webhook für die Ereignisverarbeitung zu verbinden. Sagen wir einfach "Bestätigung" unseres Webhooks.
 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.py return HttpResponse(confirmation_token, content_type="text/plain", status=200) 

Bitte beachten Sie, dass ich alle Konfigurationseinstellungen in einer separaten Bot-Konfigurationsdatei bot_config.py behalte 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 = '...' 

Und in diesem Code werden Benutzernachrichten 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 den Artikel über das erste Django-Setup lesen.

Die Magie für den Webserver . Um die Adressierung von Anforderungen an den Webserver zu konfigurieren, ging ich über den FTP-Client FileZilla zum Server im Ordner mit den Domänen und erstellte dort den Ordner " mybot.mysite.ru ". Dort wurden drei Dateien abgelegt, deren Inhalt der Hilfe auf dem Hosting entnommen wurde:

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

Hier ist "myEnv" der Name der von Ihnen erstellten virtuellen Umgebung, "django" der Ordner im Stammbereich des Dateisystems auf dem Hosting, "mybot" der Name des Projekts, das wir mit Django erstellt haben.

index.html
    

Binden Sie unseren Webhook an die Nachrichtenverarbeitung in der erstellten VKontakte-Gruppe.
Dazu kehren wir zum Abschnitt zum Verwalten unserer Gruppe auf der VKontakte-Website zurück (siehe Abbildung oben). Wir geben unsere Webhook-Adresse in das Feld "Adresse" ein
  https://mybot.mysite.ru/vk_bot/ 
und klicken Sie auf die Schaltfläche "Bestätigen". Wenn unsere Indexfunktion (Anforderungsfunktion) , die in der Datei /django/mybot/vk_bot/views.py geschrieben ist , ordnungsgemäß funktioniert, dh keine Tippfehler und Fehler enthält, wird ein grünes Häkchen angezeigt, das symbolisiert, dass alles in Ordnung ist.

Damit unser Webhook vom VKontakte-Server Nachrichten über neue Benutzernachrichten empfängt, aktivieren Sie im Abschnitt zum Verwalten unserer Gruppe auf der VKontakte-Website auf der Registerkarte "Ereignistypen" das Kontrollkästchen "Eingehende Nachrichten".

Infolgedessen empfängt 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"} 

Bitte beachten Sie, dass die json- Nachricht ein "geheimes" Feld enthält. Dies ist derselbe geheime Schlüssel, den ich im Bereich Gruppenverwaltung auf VKontakte registriert habe, anstelle des in Django CSRF integrierten Schutzes, den ich deaktivieren musste.

Wie macht man einen Bot schlauer und besser?


Sie können eine Datenbank mit Antworten für den Benutzer 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 sprechen.
Es ist möglich und notwendig, Benutzerinteraktionsszenarien sozusagen zu programmieren, um ein Gespräch aufrechtzuerhalten.

Viel Glück bei Ihrer kreativen Arbeit!

Source: https://habr.com/ru/post/de429628/


All Articles