Neste artigo, criaremos um bot e o integraremos ao grupo VK no Python 3.x
Para quem é este artigo?
Para quem deseja escrever um bot simples para sua comunidade, capaz de identificar equipes e exibir a resposta apropriada
Estágios principais
Criando um grupo de bot
Começaremos criando um bot, ou seja, um grupo no VK.
Para fazer isso, vá para "grupos" → "criar uma comunidade".
Selecione qualquer tipo de comunidade e insira um nome, tema de grupo.
Na página de configurações que é aberta, selecione "Trabalhar com a API".
Em seguida, você precisa criar uma chave de API.
Em seguida, selecione os parâmetros necessários para acessar sua chave de API.
Provavelmente, você precisará confirmar a ação no VK usando seu telefone celular. Em seguida, copie a chave da API resultante em algum lugar do arquivo. Nós ainda precisamos disso.
Então você precisa permitir mensagens. Para fazer isso, vá para a "mensagem" e ative-os. Ative também "Recursos de bot" em "Mensagens" -> "Configurações para o bot".
Lá, permitiremos adicionar uma comunidade a grupos se quisermos que o bot possa receber mensagens de um grupo.
Configurando Pesquisa Longa
Para trabalhar com a API Long Poll, usamos a biblioteca
vk_api . Você pode instalá-lo através do pip.
Antes do trabalho, salvaremos nosso token da API no arquivo config.py e, a partir daí, carregaremos nossa chave.
Vamos criar nosso primeiro script. Vamos nomear server.py, que será o principal script do servidor.
Importamos os módulos que precisamos:
import vk_api.vk_api from vk_api.bot_longpoll import VkBotLongPoll from vk_api.bot_longpoll import VkBotEventType
Crie uma classe de servidor:
class Server: def __init__(self, api_token, group_id, server_name: str="Empty"):
Agora crie o arquivo server_manager.py, no qual ele gerenciará servidores diferentes. Por enquanto, para testes, escrevemos apenas uma chamada para a classe Server:
Importante!
O bot só pode escrever mensagens para usuários que permitiram que o bot enviasse mensagens. Você pode fazer isso na página da comunidade ou escrever o bot primeiro
Se tudo for feito corretamente, o bot nos enviará uma mensagem pessoal.
Agora adicione o bot ao grupo e ensine-o a processar mensagens.
Para adicionar um bot a um grupo, clique em "Convidar para uma conversa" no menu à direita da comunidade.
Adicione a função start ao bot, após o que começará a "ouvir" as mensagens via Long Poll (não esqueça de adicionar permissões aos tipos de eventos na seção "Trabalhando com API" -> "Long Poll API" e coloque a versão mais recente):
def start(self): for event in self.long_poll.listen(): print(event)
Execute-o através do server_manager.py:
server1.start()
Agora, se escrevermos uma mensagem para o grupo, podemos ver o objeto de evento:
<< classe 'vk_api.bot_longpoll.VkBotMessageEvent'> ({'type': 'message_new', 'object': {'date': 1541273151, 'from_id': 25599999999, 'id': 0, 'out': 0, 'peer_id': 2000000001, 'text': '[club172998024 | bot in Vk] este é um texto!', 'conversation_message_id': 187, 'fwd_messages': [], 'important': False, 'random_id': 0 , 'anexos': [], 'is_hidden': False}, 'group_id': 172998024})>
Além disso, se escrevermos em mensagens privadas:
<< classe 'vk_api.bot_longpoll.VkBotMessageEvent'> ({'type': 'message_new', 'object': {'date': 1541273238, 'from_id': 25599999999, 'id': 47, 'out': 0, 'peer_id': 255396611, 'text': 'esta é uma mensagem privada', 'conversation_message_id': 47, 'fwd_messages': [], 'important': False, 'random_id': 0, 'attachments': [], 'is_hidden ': Falso},' id_grupo ': 172998024})>
A partir desses dados, devemos prestar atenção ao
tipo, object.from_id, object.id, object.peer_id, object.text . Os dados recebidos das mensagens e do grupo não diferem muito, exceto
object.peer_id e
object.id .
Se você observar atentamente, object.id para todas as mensagens do grupo é 0, mas não há mensagens de mensagens pessoais. Assim, é possível separar as mensagens recebidas do grupo e das pessoais.
Processamos os dados recebidos dentro da classe Server:
def start(self): for event in self.long_poll.listen():
Escreveremos duas mensagens para o bot: uma do grupo, uma da PM. Então temos:
Nome de usuário: Arthur
De: São Petersburgo
Texto: [club172998024 | @ club172998024] esta é uma mensagem do grupo
Tipo: mensagem de grupo
-
Nome de usuário: Arthur
De: São Petersburgo
Texto: esta é uma mensagem privada
Tipo: mensagem privada
-
Nota
Como você pode ver antes da mensagem no grupo, [club172998024 | @ club172998024], para que a equipe processe corretamente, você deve se livrar de todo o conteúdo entre colchetes ou permitir que o bot acesse toda a correspondência
Como podemos ver, vk_api nos permite usar facilmente os métodos da API VK. Por exemplo, agora usamos o método
users.getUma lista de todos os métodos está disponível em:
vk.com/dev/methodsEu aconselho você a estudar e experimentar os métodos que lhe interessam. Felizmente, o VK nos forneceu uma documentação muito boa, também em russo.
Para consolidar o material, vamos adicionar uma função para enviar uma mensagem através do método
messages.send :
def send_message(self, peer_id, message): self.vk_api.messages.send(peer_id=peer_id, message=message)
<peer_id> é o identificador de destino. Para responder à mensagem de alguém, especificaremos
event.object.peer_id como o parâmetro
peer_id . Ou seja, enviaremos uma mensagem para a origem da solicitação.
Mude o método de início:
def start(self): for event in self.long_poll.listen():
Agora, se o bot receber a mensagem, ele responderá a nós neste estilo:
Arthur, recebi sua mensagem!
Código inteiroserver.py
import vk_api.vk_api from vk_api.bot_longpoll import VkBotLongPoll from vk_api.bot_longpoll import VkBotEventType class Server: def __init__(self, api_token, group_id, server_name: str="Empty"):
server_manager.py
A tarefa de consertar o material:
Crie uma função que use o parâmetro peer_id e envie ao usuário uma foto carregada para a comunidade. Dock útil:
vk.com/dev/messages.sendSoluçãoPrimeiro, faça o upload da foto para o grupo e abra-a no VK, considere o link:
Vkcom / club172998024? z = photo-172998024_456239017 % 2Falbum-172998024_256250731
Estamos interessados apenas na parte destacada:
photo-172998024_456239017 . Passe-o como um argumento para o método messages.send:
def send_img(self, peer_id): self.vk_api.messages.send(peer_id=peer_id, attachment="photo-172998024_456239017")
Adicione-o ao método start e obtenha:

Isso é tudo o básico. O principal é aprender a usar o vk_api usando vários métodos, a lista inteira é:
vk.com/dev/methods . Se você aprender a trabalhar com a documentação da API VK, poderá criar bots de várias complexidades e propósitos. Um exemplo do meu bot para um grupo de estudo:
github.com/AppLoidx/GroupAssistant/tree/masterAgora vamos começar a criar a lógica do bot.
Crie commander.py, que aceitará comandos e retornará a resposta passada ao usuário Vk:
class Commander: def __init__(self, vk_api, user_id): self.vk_api = vk_api self.user_id = user_id def input(self, msg): """ :param msg: :return: , """ pass
Vamos construir a arquitetura do nosso programa:
Nós "ouvimos" o servidor Long Poll e recebemos uma mensagem do usuário ->
Passamos a mensagem para Commander.input () -> Definir o modo -> Definir o comando ->
Retornamos a resposta -> Transferimos para o usuário
Para definir o modo e o comando, criamos dois arquivos command_enum.py e mode_enum.py. Utilizando-os, definiremos modos e comandos através dos métodos da classe Enum:
command_enum.py:
from enum import Enum class Command(Enum): """ weather """ weather = ["weather", ""] """ myanimelist """ anime_top = ["top anime", " "]
mode_enum.py:
from enum import Enum class Mode(Enum): default = [" ", "default"] translate = [" ", "translate"] get_ans = 0
Para alterar os modos, use [slash ("/") + <mode_name>] e aceitaremos todos os outros comandos como comandos.
Implementamos isso no Commander.py:
weather.py import requests from bs4 import BeautifulSoup class Weather: @staticmethod def get_weather_today(city: str = "-") -> list: http = "https://sinoptik.com.ru/-" + city b = BeautifulSoup(requests.get(http).text, "html.parser") p3 = b.select('.temperature .p3') weather1 = p3[0].getText() p4 = b.select('.temperature .p4') weather2 = p4[0].getText() p5 = b.select('.temperature .p5') weather3 = p5[0].getText() p6 = b.select('.temperature .p6') weather4 = p6[0].getText() result = '' result = result + (' :' + weather1 + ' ' + weather2) + '\n' result = result + (' :' + weather3 + ' ' + weather4) + '\n' temp = b.select('.rSide .description') weather = temp[0].getText() result = result + weather.strip() return result
myanimelist.py import requests import bs4 class Myanimelist: @staticmethod def get_top(count: int=5, by: str="") -> dict: types = ["", "airing", "upcoming", "tv", "movie", "ova", "special", "bypopularity", "favorite"] if by not in types: return {"error: ": " !"} html = requests.get("https://myanimelist.net/topanime.php?type="+by) soup = bs4.BeautifulSoup(html.text, "html.parser") res = {} for anime in soup.select(".ranking-list", limit=count): url = anime.select(".hoverinfo_trigger")[0]['href'] anime = anime.select(".hoverinfo_trigger")[0].findAll("img")[0] name = anime['alt'].split(":")[1].strip(" ") res[name] = url return res
yandex_translate.py import requests from config import yandex_translate_api class Translator: """ - API Yandex Translate : _key -- API Yandex.Translate _yandex_comment -- API Yandex.Translate """ def __init__(self, key, comment=None): """ :param key: API Yandex.Translate :param comment: """ self._key = key if comment is None: self._yandex_comment = "\n «.» http://translate.yandex.ru/" else: self._yandex_comment = comment def translate(self, text, lang, to_lang=None): """ :param text: , :param lang: :param to_lang: :return: """ if to_lang is not None: lang = f"{lang}-{to_lang}" main_url = "https://translate.yandex.net/api/v1.5/tr.json/translate" response = requests.get(f"{main_url}?" f"key={self._key}&" f"lang={lang}&" f"text={text}") return response.json()['text'][0] + self._yandex_comment def lang_identify(self, text, hint="ru,en"): """ :param text: :param hint: :return: """ main_url = "https://translate.yandex.net/api/v1.5/tr.json/detect" response = requests.get(f"{main_url}?" f"key={self._key}&" f"hint={hint}&" f"text={text}") return response.json()['lang'] def translate_ru_en(self, text): """ :param text: , :return: """ if self.lang_identify(text) == "ru": to_lang = "en" from_lang = "ru" else: to_lang = "ru" from_lang = "en" return self.translate(text, from_lang, to_lang) def translate_to_ru(self, text, hint=None): """ :param text: , :param hint: :return: """ if hint is None: hint = "ru,en" from_lang = self.lang_identify(text, hint) return self.translate(text, from_lang, "ru") def translate_to(self, text, to_lang, hint=None): """ :param text: , :param to_lang: :param hint: :return: """ if hint is None: hint = "ru,en" from_lang = self.lang_identify(text, hint) return self.translate(text, from_lang, to_lang)
Todo o código está disponível no github:
github.com/AppLoidx/VkLongPollBotAdicione um teclado:
Este é um processo muito fácil. Podem ocorrer complicações quando alteramos o teclado para uma assinatura específica de comandos, diferente para cada modo.
Para adicionar um teclado à caixa de diálogo, você deve especificar o parâmetro de teclado que aceita json no método messages.send. É assim:
vk_api.messages.send(...,keyboard=keyboard_json,...)
Ou você pode passar o teclado diretamente do arquivo .json:
vk_api.messages.send(...,keyboard=open(filename,"r",encoding="UTF-8").read()
Documentação:
vk.com/dev/bots_docs_3?f=4.%2BKeyboard%2Bfor%2BworksConsidere o exemplo do nosso programa adicionando um teclado.
Primeiro, crie um arquivo keyboard.json:
{ "one_time": false, "buttons": [ [{ "action": { "type": "text", "label": "top anime" }, "color": "positive" }, { "action": { "type": "text", "label": "weather" }, "color": "positive" }], [{ "action": { "type": "text", "label": "translate" }, "color": "default" }] ] }
Para remover o teclado, você precisa passar o json com botões vazios:
{"buttons":[],"one_time":true}
Substitua send_message em server.py:
def send_msg(self, send_id, message): """ messages.send :param send_id: vk id , :param message: :return: None """ return self.vk_api.messages.send(peer_id=send_id, message=message, keyboard=open("keyboards/default.json", "r", encoding="UTF-8").read())
E também no método start:
def start(self): for event in self.long_poll.listen():
Como resultado, obtemos:

Última palavra
Você não deve usar a lista
simples dos códigos-fonte apresentados aqui, eles são usados apenas para que você entenda melhor o que está acontecendo sob o capô. Obviamente, eles são todos utilizáveis e você pode usá-los em partes.
Pessoalmente, usei esse bot para um assistente de grupo que sabia como:
- crie filas de membros do grupo, incluindo muitas equipes que editaram a fila, como adicionar, excluir, criar etc.
- envie mensagens para todos os participantes
- perguntas mais frequentes (por exemplo, em Java)
- tornou possível criar aplicativos para troca de lugares etc.
Projeto GithubFontes aqui apresentadas