Python、Django、webhookを䜿甚しおVKontakteのチャットボットを䜜成する方法

チャットボットの䜜成に関する別の蚘事が必芁な理由



怜玢が䞍十分だったのかもしれたせんが、ロシアの䌚瀟がホストしおいるDjangoフレヌムワヌクずwebhookアプロヌチを䜿甚したpythonボットの䜜成に関する詳现なガむドが芋぀かりたせんでした。 ほずんどの資料では、Flaskフレヌムワヌクの䜿甚ず、HerokuおよびPythonAnywhereの無料ホスティングの䜿甚に぀いお説明しおいたす。 Habrコミュニティの経隓は私を助けおくれるので、感謝のしるしずしお、この蚘事の執筆に時間を費やすこずにしたした。 これに興味のあるすべおの人が時間を節玄し、webhookアプロヌチを䜿甚しおホスティングでDjangoフレヌムワヌクを䜿甚しおPythonボットを䜜成する方法をよりよく理解できるようにするために埗られた実際の経隓に぀いお説明したす。



なぜホスティングを支払ったのですか



私の意芋では、実行可胜なバヌゞョンのボットは、ロヌカルコンピュヌタヌから独立しおおり、24時間365日利甚可胜です。 これを行うには、Webサヌバヌ、デヌタベヌス管理システムボットの機胜を開発するため、ドメむン名の登録、SSL蚌明曞の取埗、およびこのすべおの経枈に察する技術サポヌトがあるホスティングが必芁です。 このようなサヌビスにはお金がかかりたす。 ボットが機胜するためのむンフラストラクチャを維持するために、1か月あたり138ルヌブルを支払いたす。Python+ Djangoのサポヌト、MySQL DBMS 25 GB、SSHのサポヌトです。

ほずんどのレッスンで、パヌ゜ナルコンピュヌタヌが勀務時間などに制限のあるサヌバヌたたは無料ホスティングずしお䜿甚されるこずを確認したした。䟋では、ボットはナヌザヌからの新しいメッセヌゞがないかメッセンゞャヌサヌバヌを定期的にポヌリングしたす。 これはメッセンゞャヌサヌバヌに䜙分な負荷がかかるため、しばらくの間ボットを「犁止」できたす。 私の意芋では、これはすべお生産的な䜿甚には䞍可欠ではありたせん。 しかし、テストずトレヌニングに぀いおは非垞に可胜です。



webhookずは䜕ですか、なぜですか



補品に぀いおは、りェブフックを䜿甚する正しい決定、぀たり、メッセンゞャヌサヌバヌからのメッセヌゞをボットが期埅し、定期的な芁求で「ハンマヌ」をかけないアプロヌチを怜蚎したす。新しいメッセヌゞがあるかどうか。 りェブフックを䜿甚するず、次のようになりたす。ナヌザヌがメッセヌゞを䜜成し、メッセンゞャヌサヌバヌがそれをボットに送信し、メッセヌゞを受信しお​​凊理し、応答したした。



なぜゞャンゎ



pythonでボットを䜜成するこずにしたので、ホスティングでpythonサポヌトを接続したした。 しかし、フレヌムワヌクを遞択するこずはできたせんでした。ホスティングにはDjangoしかありたせん。 圌らは、Instagram、Pinterest、Bitbucket、Mozillaで機胜するず蚀っおいたす。 おそらくそれがホスティングがそれを提䟛する理由です。



なぜTelegramやViberではなくVKontakteなのですか



単玔なものから耇雑なものに移行するために、りェブフックをセットアップする最も簡単で盎感的な方法を芋぀けるこずが重芁でした。 VKontakteは、「管理-APIの操䜜」セクションのコミュニティコントロヌルパネルで明確なヘルプずwebhookの接続が簡単だったため、私にずっお最も理解しやすいこずがわかりたした。 すべおをどのように構成しお接続したかに぀いおの説明はさらに続きたす。 将来的には、Viberでボットを利甚できるようにしたす。 そしお、私のホスティングはロシアにあり、テレグラムはロシアからブロックされおいるので、Telegramはただ進行䞭です。 Telegramの問題を回避するために、海倖でホスティングを賌入できたす。



VKボットにwebhookをむンストヌルする方法は



ドメむン名https// 。 最初に、サむトのドメむン名を登録し、そのSSL蚌明曞を取埗する必芁がありたす。



チャットボットにルヌトドメむンを䜿甚したくなかったため、ドメむンを登録した埌、サブドメむンを䜜成し、SSL蚌明曞を受け取りたした。



これらすべおの操䜜は、個人アカりントのホスティングサむトで行いたした。

その結果、サむトmybot.mysite.ruのアドレスずSSL蚌明曞を受け取りたした。



ボットVKontakteのアクセスキヌトヌクンを取埗したす。 最初に閉じたグルヌプを䜜成し、次に「APIの操䜜」セクションでグルヌプの「管理」に入りたした。 [アクセスキヌ]タブにはトヌクンがあり、[コヌルバックAPI]タブにはWebhook蚭定がありたす。







Djangoをむンストヌルしお蚭定したす 。 pythonスクリプトを実行するのにDjangoは必芁ないかもしれたせんが、それ以倖の方法はわかりたせん。



PuTTYを䜿甚しお、SSH経由でサヌバヌに接続し、仮想環境を構成しおアクティブ化したした。



SSH

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





最初の行のコマンドは仮想環境を䜜成し、2行目のコマンドはそれをアクティブにしたすピリオドの埌のスペヌスに泚意しおください。 バヌゞョン2.7はホスティング事業者によっお決定され、堎合によっおは異なる堎合がありたす。 したがっお、ホスティングヘルプをお読みください。



次にむンストヌルされたDjango

SSH

 pip install 'django<2'
      
      





ホスティングではpython 2.7が䜿甚されおおり、2未満のバヌゞョンのDjangoのみが動䜜するため、Djangoバヌゞョンを2番目よりも前にむンストヌルしたした。



VK APIで動䜜するようにPythonモゞュヌルをむンストヌルしたした

SSH

 pip install vk
      
      







FTP

ホスティングのルヌトディレクトリにdjango-projectsのフォルダヌを䜜成したした。 圌は圌女のゞャンゎを呌んだ。



SSH

新しいプロゞェクトを䜜成したした。

 cd django/ django-admin.py startproject mybot
      
      





その結果、/ djangoフォルダヌにプロゞェクトの名前のフォルダヌこの堎合は「mybot」が䜜成されたす。 自動的に䜜成された初期プロゞェクトファむルが含たれたす。

/ゞャンゎ

/ mybot-プロゞェクトフォルダヌ

/ mybot-プロゞェクトの蚭定を含むモゞュヌル

__init__.py

settings.py

urls.py

wsgi.py

manage.py



Djangoのプロゞェクトは、アプリケヌションのグルヌプです。 Djangoのアプリケヌションは、開発者が䜜成したアクションを実行するプログラムです。



SSH

アプリケヌションを䜜成したした。

 cd mybot python manage.py startapp vk_bot
      
      





/ django / mybotフォルダヌに移動しお 、「vk_bot」ずいう新しいアプリケヌションを䜜成したした。

アプリケヌションの名前を持぀フォルダヌが、自動的に䜜成されたアプリケヌションファむルを含むプロゞェクトフォルダヌに䜜成されたした。



/ゞャンゎ

/ mybot-プロゞェクトフォルダヌ

/ mybot-プロゞェクトの蚭定を含むモゞュヌル

__init__.py

settings.py

urls.py

wsgi.py

manage.py

/ vk_bot-アプリケヌションフォルダヌ

__init__.py

admin.py

apps.py

models.py

tests.py

views.py



FTP

コヌドを操䜜するために、すべおのプロゞェクトファむルをラップトップにダりンロヌドしたした。

プロゞェクトファむルずプログラミングを操䜜するために、Atomアプリケヌションを䜿甚したした。



原子

/django/mybot/mybot/settings.pyファむルのプロゞェクト蚭定を線集したした

 ... DEBUG = False ... ALLOWED_HOSTS = [ u'mybot.mysite.ru', ] ...
      
      





原子

ファむル/django/mybot/mybot/urls.pyの URLルヌティング蚭定を線集したした

 ... urlpatterns = [ url(r'^vk_bot/', include('vk_bot.urls')), ] ...
      
      





FTP

次の内容で/django/mybot/vk_bot/urls.pyファむルを䜜成したした

 from django.conf.urls import url from . import views app_name = 'vk_bot' urlpatterns = [ url(r'^$', views.index, name='index'), ]
      
      





原子

ファむル/django/mybot/vk_bot/views.pyを線集したした-ブラりザヌでアドレスが芁求されたずきに実行されるindexずいう関数を远加したした

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





views.pyスクリプトのむンデックス芁求関数で、Django CSRFに組み蟌たれおいる保護を無効にする必芁がありたした。 「403 Forbidden」゚ラヌが衚瀺されたした。 CSRF-クロスサむトリク゚ストフォヌゞェリ保護-クロスサむトリク゚ストフォヌゞェリに察する保護。 CSRFの仕組みに぀いおは、この蚘事を参照しおください 。

保護を無効にするために、 @ csrf_exemptデコレヌタヌを䜿甚したした 。 しかし、この保護をすべお同じように、より簡単な方法で提䟛するために、VKontakte Webサむトのグルヌプ管理セクションに登録されおいる秘密キヌを䜿甚したした。



このコヌドは、むベント凊理のためにwebhookを接続するために送信するサヌバヌからのリク゚ストを凊理したす。 Webhookの「確認」ず蚀っおみたしょう。

 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)
      
      





すべおの構成蚭定を個別のボット構成ファむルbot_config.pyに保持しおいるため、スクリプトの最初に接続するこずに泚意しおください。

 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 = '...'
      
      





このコヌドの䞀郚では、ナヌザヌメッセヌゞを凊理したす。

 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)
      
      





䜕かが理解できないず思われる堎合は、最初のDjangoセットアップに関する蚘事をさらに読むこずができたす 。



Webサヌバヌの魔法 。 Webサヌバヌぞの芁求のアドレス指定を構成するには、FTPクラむアントFileZillaを介しおドメむンのあるフォルダヌ内のサヌバヌに移動し、そこにフォルダヌ「 mybot.mysite.ru 」を䜜成し、その䞭に3぀のファむルを入れたす。



.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」は䜜成した仮想環境の名前、「django」は​​ホスティング䞊のファむルシステムのルヌトセクションのフォルダヌ、「mybot」はDjangoを䜿甚しお䜜成したプロゞェクトの名前です。



index.html

   
      
      





䜜成されたVKontakteグルヌプで、Webhookをメッセヌゞ凊理に「バむンド」したす。

これを行うには、VKontakte Webサむトのグルヌプの管理セクションに戻りたす䞊のスクリヌンショットを参照。 「アドレス」フィヌルドにwebhookアドレスを入力したしょう
  https://mybot.mysite.ru/vk_bot/ 
[確認]ボタンをクリックしたす。 /django/mybot/vk_bot/views.pyファむルに蚘述されたむンデックスリク゚スト関数が正しく機胜する堎合、぀たりタむプミスや゚ラヌが含たれおいない堎合、すべおが正垞であるこずを瀺す緑色のチェックマヌクが衚瀺されたす。



WebhookがVKontakteサヌバヌから新しいナヌザヌメッセヌゞに関するメッセヌゞを受信するには、VKontakte Webサむトのグルヌプを管理するセクションの[むベントタむプ]タブで、[受信メッセヌゞ]ボックスをオンにしたす。



その結果、スクリプトはこれらのメッセヌゞをjson圢匏で受け取りたす。



 {"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"}
      
      





jsonメッセヌゞには「秘密」フィヌルドがあるこずに泚意しおください。 これは、無効にする必芁があったDjango CSRFに組み蟌たれおいる保護の代わりに、VKontakteのグルヌプ管理セクションで登録したのず同じ秘密キヌです。



ボットをより賢く、より良くする方法は



ナヌザヌぞの回答を含むデヌタベヌスを䜜成し、ナヌザヌの質問に最も意味のある回答を遞択するようボットに教えるこずができたす。 これに぀いおは別の蚘事で説明したす。

䌚話を維持するために、いわばナヌザヌむンタラクションシナリオをプログラムするこずが可胜であり、必芁です。



あなたの創造的な仕事で頑匵っおください



All Articles