Разное

Python боты создание: Как создать чат-бота с нуля на Python: подробная инструкция

Содержание

Как создать чат-бота с нуля на Python: подробная инструкция

Аналитики Gartner утверждают, что к 2020 году 85% взаимодействий клиентов с сервисами сведется к общению с чат-ботами. В 2018 году они уже обрабатывают около 30% операций. В этой статье мы расскажем, как создать своего чат-бота на Python.

Возможно, вы слышали о Duolingo: популярном приложении для изучения иностранных языков, в котором обучение проходит в форме игры. Duolingo популярен благодаря инновационному стилю обучения. Концепция проста: от пяти до десяти минут интерактивного обучения в день достаточно, чтобы выучить язык.

Несмотря на то что Duolingo позволяет изучить новый язык, у пользователей сервиса возникла проблема. Они почувствовали, что не развивают разговорные навыки, так как обучаются самостоятельно. Пользователи неохотно обучались в парах из-за смущения. Эта проблема не осталась незамеченной для разработчиков.

Команда сервиса решила проблему, создав чат-бота в приложении, чтобы помочь пользователям получать разговорные навыки и применять их на практике.

Поскольку боты разрабатывались так, чтобы быть разговорчивыми и дружелюбными, пользователи Duolingo практикуются в общении в удобное им время, выбирая «собеседника» из набора, пока не поборят смущение в достаточной степени, чтобы перейти к общению с другими пользователями. Это решило проблему пользователей и ускорило обучение через приложение.

Итак, что такое чат-бот?

Чат-бот — это программа, которая выясняет потребности пользователей, а затем помогает удовлетворить их (денежная транзакция, бронирование отелей, составление документов). Сегодня почти каждая компания имеет чат-бота для взаимодействия с пользователями. Некоторые способы использования чат-ботов:

  • предоставление информации о рейсе;
  • предоставление пользователям доступа к информации об их финансах;
  • служба поддержки.

Возможности безграничны.

История чат-ботов восходит к 1966 году, когда Джозеф Вейценбаум разработал компьютерную программу ELIZA. Программа подражает манере речи психотерапевта и состоит лишь из 200 строк кода. Пообщаться с Элизой можно до сих пор на сайте.

Как работает чат-бот?

Существует два типа ботов: работающие по правилам и самообучающиеся.

  • Бот первого типа отвечает на вопросы, основываясь на некоторых правилах, которым он обучен. Правила могут быть как простыми, так и очень сложными. Боты могут обрабатывать простые запросы, но не справлятся со сложными.
  • Самообучающиеся боты создаются с использованием основанных на машинном обучении методов и определенно более эффективны, чем боты первого типа. Самообучающиеся боты бывают двух типов: поисковые и генеративные.

В поисковых ботах используются эвристические методы для выбора ответа из библиотеки предопределенных реплик. Такие чат-боты используют текст сообщения и контекст диалога для выбора ответа из предопределенного списка. Контекст включает в себя текущее положение в древе диалога, все предыдущие сообщения и сохраненные ранее переменные (например, имя пользователя). Эвристика для выбора ответа может быть спроектирована по-разному: от условной логики «или-или» до машинных классификаторов.

Генеративные боты могут самостоятельно создавать ответы и не всегда отвечают одним из предопределенных вариантов. Это делает их интеллектуальными, так как такие боты изучают каждое слово в запросе и генерируют ответ.

В этой статье мы научимся писать код простых поисковых чат-ботов на основе библиотеки NLTK.

Создание бота на Python

Предполагается, что вы умеете пользоваться библиотеками scikit и NLTK. Однако, если вы новичок в обработке естественного языка (NLP), вы все равно можете прочитать статью, а затем изучить соответствующую литературу.

Обработка естественного языка (NLP)

Обработка естественного языка — это область исследований, в которой изучается взаимодействие между человеческим языком и компьютером. NLP основана на синтезе компьютерных наук, искусственного интеллекта и вычислительной лингвистики. NLP — это способ для компьютеров анализировать, понимать и извлекать смысл из человеческого языка разумным и полезным образом.

Краткое введение в NLKT

NLTK (Natural Language Toolkit) — платформа для создания программ на Python для работы с естественной речью. NLKT предоставляет простые в использовании интерфейсы для более чем 50 корпораций и лингвистических ресурсов, таких как WordNet, а также набор библиотек для обработки текста в целях классификации, токенизации, генерации, тегирования, синтаксического анализа и понимания семантики, создания оболочки библиотек NLP для коммерческого применения.

Книга Natural Language Processing with Python  — практическое введение в программирование для обработки языка. Рекомендуем ее прочитать, если вы владеете английским языком.

Загрузка и установка NLTK

  • Установите NLTK: запустите pip install nltk.
  • Тестовая установка: запустите python, затем введите import nltk.

Инструкции для конкретных платформ смотрите здесь.

Установка пакетов NLTK

Импортируйте NLTK и запустите nltk.download(). Это откроет загрузчик NLTK, где вы сможете выбрать версию кода и модели для загрузки. Вы также можете загрузить все пакеты сразу.

Предварительная обработка текста с помощью NLTK

Основная проблема с данными заключается в том, что они представлены в текстовом формате. Для решения задач алгоритмами машинного обучения требуется некий вектор свойств. Поэтому прежде чем начать создавать проект по NLP, нужно предварительно обработать его. Предварительная обработка текста включает в себя:

  • Преобразование букв в заглавные или строчные, чтобы алгоритм не обрабатывал одни и те же слова повторно.
  • Токенизация. Токенизация — термин, используемый для описания процесса преобразования обычных текстовых строк в список токенов, то есть слов. Токенизатор предложений используется для составления списка предложений. Токенизатор слов составляет список слов.

Пакет NLTK включает в себя предварительно обученный токенизатор Punkt для английского языка.

  • Удаление шума, то есть всего, что не является цифрой или буквой;
  • Удаление стоп-слов. Иногда из словаря полностью исключаются некоторые крайне распространенные слова, которые, как считается, не имеют большого значения для формирования ответа на вопрос пользователя. Эти слова называются стоп-словами (междометия, артикли, некоторые вводные слова);
  • Cтемминг: приведение слова к коренному значению. Например, если нам нужно провести стемминг слов «стемы», «стемминг», «стемированный» и «стемизация», результатом будет одно слово — «стем».
  • Лемматизация. Лемматизация — немного отличающийся от стемминга метод. Основное различие между ними заключается в том, что стемминг часто создает несуществующие слова, тогда как лемма — это реально существующее слово. Таким образом, ваш исходный стем, то есть слово, которое получается после стемминга, не всегда можно найти в словаре, а лемму — можно. Пример лемматизации: «run» — основа для слов «running» или «ran», а «better» и «good» находятся в одной и той же лемме и потому считаются одинаковыми.

Набор слов

После первого этапа предварительной обработки нужно преобразовать текст в вектор (или массив) чисел. «Набор слов» — это представление текста, описывающего наличие слов в тексте. «Набор слов» состоит из:

  • словаря известных слов;
  • частот, с которыми каждое слово встречается в тексте.

Почему используется слово «набор»? Это связано с тем, что информация о порядке или структуре слов в тексте отбрасывается, и модель учитывает только то, как часто определенные слова встречаются в тексте, но не то, где именно они находятся.

Идея «набора слов» состоит в том, что тексты похожи по содержанию, если включают в себя похожие слова. Кроме того, кое-что узнать о содержании текста можно лишь по набору слов.

Например, если словарь содержит слова {Learning, is, the, not, great} и мы хотим составить вектор предложения “Learning is great”, получится вектор (1, 1, 0, 0, 1).

Метод TF-IDF

Проблема «набора слов» заключается в том, что в тексте могут доминировать часто встречающиеся слова, которые не содержат ценную для нас информацию. Также «набор слов» присваивает большую важность длинным текстам по сравнению с короткими.

Один из подходов к решению этих проблем состоит в том, чтобы вычислять частоту появления слова не в одном тексте, а во всех сразу. За счет этого вклад, например, артиклей «a» и «the» будет нивелирован. Такой подход называется TF-IDF (Term Frequency-Inverse Document Frequency) и состоит из двух этапов:

  • TF — вычисление частоты появления слова в одном тексте
TF = (Число раз, когда слово "t" встречается в тексте)/(Количество слов в тексте)
  • IDF — вычисление того, на сколько редко слово встречается во всех текстах
IDF = 1+log(N/n), где N - общее количество текстов, n - во скольких текстах встречается "t"

Коэффициент TF-IDF — это вес, часто используемый для обработки информации и интеллектуального анализа текста. Он является статистической мерой, используемой для оценки важности слова для текста в некотором наборе текстов.

Пример

Рассмотрим текст, содержащий 100 слов, в котором слово «телефон» появляется 5 раз. Параметр TF для слова «телефон» равен (5/100) = 0,05.

Теперь предположим, что у нас 10 миллионов документов, и слово телефон появляется в тысяче из них. Коэффициент вычисляется как 1+log(10 000 000/1000) = 4. Таким образом, TD-IDF равен 0,05 * 4 = 0,20.

TF-IDF может быть реализован в scikit так:

from sklearn.feature_extraction.text import TfidfVectorizer

Коэффициент Отиаи

TF-IDF — это преобразование, применяемое к текстам для получения двух вещественных векторов в векторном пространстве. Тогда мы можем получить коэффициент Отиаи любой пары векторов, вычислив их поэлементное произведение и разделив его на произведение их норм. Таким образом, получается косинус угла между векторами. Коэффициент Отиаи является мерой сходства между двумя ненулевыми векторами. Используя эту формулу, можно вычислить схожесть между любыми двумя текстами d1 и d2.

Cosine Similarity (d1, d2) =  Dot product(d1, d2) / ||d1|| * ||d2||

Здесь d1, d2 — два ненулевых вектора.

Подробное объяснение и практический пример TF-IDF и коэффициента Отиаи приведены в посте по ссылке.

Пришло время перейти к решению нашей задачи, то есть созданию чат-бота. Назовем его «ROBO».

Обучение чат-бота

В нашем примере мы будем использовать страницу Википедии в качестве текста. Скопируйте содержимое страницы и поместите его в текстовый файл под названием «chatbot.txt». Можете сразу использовать другой текст.

Импорт необходимых библиотек

import nltk
import numpy as np
import random
import string # to process standard python strings

Чтение данных

Выполним чтение файла corpus.txt и преобразуем весь текст в список предложений и список слов для дальнейшей предварительной обработки.

f=open('chatbot.txt','r',errors = 'ignore')
raw=f.read()
raw=raw.lower()# converts to lowercase
nltk.download('punkt') # first-time use only
nltk.download('wordnet') # first-time use only
sent_tokens = nltk.sent_tokenize(raw)# converts to list of sentences 
word_tokens = nltk.word_tokenize(raw)# converts to list of words

Давайте рассмотрим пример файлов sent_tokens и word_tokens

sent_tokens[:2]
['a chatbot (also known as a talkbot, chatterbot, bot, im bot, interactive agent, or artificial conversational entity) is a computer program or an artificial intelligence which conducts a conversation via auditory or textual methods.',
 'such programs are often designed to convincingly simulate how a human would behave as a conversational partner, thereby passing the turing test.']
word_tokens[:2]
['a', 'chatbot', '(', 'also', 'known']

Предварительная обработка исходного текста

Теперь определим функцию LemTokens, которая примет в качестве входных параметров токены и выдаст нормированные токены.

lemmer = nltk.stem.WordNetLemmatizer()
#WordNet is a semantically-oriented dictionary of English included in NLTK.
def LemTokens(tokens):
    return [lemmer.lemmatize(token) for token in tokens]
remove_punct_dict = dict((ord(punct), None) for punct in string.punctuation)
def LemNormalize(text):
    return LemTokens(nltk.word_tokenize(text.lower().translate(remove_punct_dict)))

Подбор ключевых слов

Определим реплику-приветствие бота. Если пользователь приветствует бота, бот поздоровается в ответ. В ELIZA используется простое сопоставление ключевых слов для приветствий. Будем использовать ту же идею.

GREETING_INPUTS = ("hello", "hi", "greetings", "sup", "what's up","hey",)
GREETING_RESPONSES = ["hi", "hey", "*nods*", "hi there", "hello", "I am glad! You are talking to me"]
def greeting(sentence):
 
    for word in sentence.split():
        if word.lower() in GREETING_INPUTS:
            return random.choice(GREETING_RESPONSES)

Генерация ответа

Чтобы сгенерировать ответ нашего бота для ввода вопросов, будет использоваться концепция схожести текстов. Поэтому мы начинаем с импорта необходимых модулей.

from sklearn.metrics.pairwise import cosine_similarity

Этот модуль будет использоваться для поиска в запросе пользователя ключевых слов. Это самый простой способ создать чат-бота.

Определим функцию отклика, которая возвращает один из нескольких возможных ответов. Если запрос не соответствует ни одному ключевому слову, бот выдает ответ «Извините! Я вас не понимаю».

def response(user_response):
    robo_response=''
TfidfVec = TfidfVectorizer(tokenizer=LemNormalize, stop_words='english')
    tfidf = TfidfVec.fit_transform(sent_tokens)
    vals = cosine_similarity(tfidf[-1], tfidf)
    idx=vals.argsort()[0][-2]
    flat = vals.flatten()
    flat.sort()
    req_tfidf = flat[-2]
    if(req_tfidf==0):
        robo_response=robo_response+"I am sorry! I don't understand you"
        return robo_response
    else:
        robo_response = robo_response+sent_tokens[idx]
        return robo_response

Наконец, мы задаем реплики бота в начале и конце переписки, в зависимости от реплик пользователя.

flag=True
print("ROBO: My name is Robo. I will answer your queries about Chatbots. If you want to exit, type Bye!")
while(flag==True):
    user_response = input()
    user_response=user_response.lower()
    if(user_response!='bye'):
        if(user_response=='thanks' or user_response=='thank you' ):
            flag=False
            print("ROBO: You are welcome..")
        else:
            if(greeting(user_response)!=None):
                print("ROBO: "+greeting(user_response))
            else:
                sent_tokens.append(user_response)
                word_tokens=word_tokens+nltk.word_tokenize(user_response)
                final_words=list(set(word_tokens))
                print("ROBO: ",end="")
                print(response(user_response))
                sent_tokens.remove(user_response)
    else:
        flag=False
        print("ROBO: Bye! take care..")

Вот и все. Мы написали код нашего первого бота в NLTK. Здесь вы можете найти весь код вместе с текстом. Теперь давайте посмотрим, как он взаимодействует с людьми:

Получилось не так уж плохо. Даже если чат-бот не смог дать удовлетворительного ответа на некоторые вопросы, он хорошо справился с другими.

Заключение

Хотя наш примитивный бот едва ли обладает когнитивными навыками, это был неплохой способ разобраться с NLP и узнать о работе чат-ботов. «ROBO», по крайней мере, отвечает на запросы пользователя. Он, конечно, не обманет ваших друзей, и для коммерческой системы вы захотите рассмотреть одну из существующих бот-платформ или фреймворки, но этот пример поможет вам продумать архитектуру бота.


Интересные статьи:

Создание Discord-бота на Python. Часть 1 / Хабр

Версии, которые стоят у автора

Версия Python: 3.8.2

Версия discord.py: 1.3.3

Приветствую, хабровчане и другие пользователи интернета. Сегодня я начну цикл статей, посвящённых созданию Discord-бота с помощью библиотеки discord.py. Мы рассмотрим создание как и примитивного бота, как и «продвинутого» бота с модулями. В этой статье мы сделаем стандартную команду и ещё одну небольшую команду. Начнём!

Создание бота и получение токена

Для того, чтобы добавить бота на сервер нужно создать свое приложение и во вкладке General Information скопировать Client ID.

Здесь заменяем CLID на ранее скопированный Client ID.

https://discordapp.com/oauth3/authorize?&client_id=CLID&scope=bot&permissions=8

Во вкладке Bot создаём бота и копируем токен.

Написание кода

Устанавливаем саму библиотеку.

pip install discord

Создаём файл config.py (так удобнее), и создаём там словарь.

settings = {
    'token': 'Ваш токен',
    'bot': 'Имя бота',
    'id': Client ID бота, без кавычек,
    'prefix': 'Префикс бота'
}

Создаём main-файл, название может быть любое.

Импортируем библиотеки и наш файл конфига:

import discord
from discord.ext import commands
from config import settings

Создаём «тело» бота, название может быть любое:

bot = commands.Bot(command_prefix = settings['prefix']) # Так как мы указали префикс в settings, обращаемся к словарю с ключом prefix.

Начинаем писать основной код.

@bot.command() # Не передаём аргумент pass_context, так как он был нужен в старых версиях.
async def hello(ctx): # Создаём функцию и передаём аргумент ctx.
    author = ctx.message.author # Объявляем переменную author и записываем туда информацию об авторе.

    await ctx.send(f'Hello, {author.mention}!') # Выводим сообщение с упоминанием автора, обращаясь к переменной author.

В конце запускаем бота с помощью:

bot.run(settings['token']) # Обращаемся к словарю settings с ключом token, для получения токена

Полный код

import discord
from discord.ext import commands
from config import settings

bot = commands.Bot(command_prefix = settings['prefix'])

@bot.command() # Не передаём аргумент pass_context, так как он был нужен в старых версиях.
async def hello(ctx): # Создаём функцию и передаём аргумент ctx.
    author = ctx.message.author # Объявляем переменную author и записываем туда информацию об авторе.
    await ctx.send(f'Hello, {author.mention}!') # Выводим сообщение с упоминанием автора, обращаясь к переменной author.

bot.run(settings['token']) # Обращаемся к словарю settings с ключом token, для получения токена

Должно получится так:

Бонусный туториал!

Сделаем вывод случайных картинок с лисами

Для этого импортируем еще пару библиотек:

import json
import requests

Приступим к написанию команды.

@bot.command()
async def fox(ctx):
    response = requests.get('https://some-random-api.ml/img/fox') # Get-запрос
    json_data = json.loads(response.text) # Извлекаем JSON

    embed = discord.Embed(color = 0xff9900, title = 'Random Fox') # Создание Embed'a
    embed.set_image(url = json_data['link']) # Устанавливаем картинку Embed'a
    await ctx.send(embed = embed) # Отправляем Embed

Должно получится так:

Конец

На этом 1 часть закончена. Скоро будет опубликована 2 часть.

Создание простого чат-бота в VK на Python 3 / Хабр

Создание основы для работы бота будет состоять из следующих этапов:

  1. Создание бота в ВК
  2. Генерирование API- ключа
  3. Создание программы бота через LongPoolVK

Для кого эта статья?

Статья рассчитана для начинающих программистов. Метод работы программы очень прост и любой, кто умеет разбираться в синтаксисе Питона и немного знающий ООП сможет его реализовать для своих нужд. Но в принципе даже не зная никаких принципов ООП, думаю можно научиться добавлять простые функции или хотя бы в крайнем случае использовать готовые исходники из GitHub.

Что есть в этой статье?

Создание основы бота. После этого его можно будет запрограммировать как-угодно. Автоматизировать какую-то рутину или использовать как собеседник.

Улучшенная (слегка усложненная версия бота). Я решил сначала представить простой процедурный код бота, а затем слегка усложнить его, добавив функции, значительно улучшающие работу бота.

Добавление функции передачи погоды. Научим бота говорить нам погоду.

Создание бота в ВК

Начнем мы с создания бота, а именно группу в ВК.

Для это нужно зайти в «группы» → «создать сообщество».

Выберите любой тип сообщества и введите название, тематику группы.

На открывшейся странице настроек, выберите «Работа с API»

Далее, необходимо создать API-ключ.

Затем выберите нужные вам параметры с доступом для вашего API-ключа.

Скорее всего, вам придётся подтверждать действие в ВК с помощью мобильного телефона. Затем скопируйте полученный API-ключ где-нибудь в файл. Он нам еще понадобится.

Затем нужно разрешить сообщения. Для этого переходим в «сообщения» и включаем их.

Приступим к программной части бота

Мы не будем реализовывать его через запросы к ВК, а если быть точнее, просто используем библиотеку VkLongPool, которая сделает это за нас.

Для этого необходима библиотека vk_api. Установим его через pip:

python -m pip install vk_api

Но лично я работаю с виртуальным окружением Anaconda. С этим зачастую возникают проблемы при первой работе. Обычно проблема в том, что система не распознают команду «python». А решается эта проблема путем добавления его в PATH.

Приступим к самому коду:

Импортируем нужные модули:

import vk_api
from vk_api.longpoll import VkLongPoll, VkEventType

Затем код:

def write_msg(user_id, message):
    vk.method('messages.send', {'user_id': user_id, 'message': message})

# API-ключ созданный ранее
token = "6a9c267cd469388709a9e9acaddbe0aa81a0abbf12239b3e597a31729ffbddb9c88e80a443554c918b8f7"

# Авторизуемся как сообщество
vk = vk_api.VkApi(token=token)

# Работа с сообщениями
longpoll = VkLongPoll(vk)

# Основной цикл
for event in longpoll.listen():

    # Если пришло новое сообщение
    if event.type == VkEventType.MESSAGE_NEW:
    
        # Если оно имеет метку для меня( то есть бота)
        if event.to_me:
        
            # Сообщение от пользователя
            request = event.text
            
            # Каменная логика ответа
            if request == "привет":
                write_msg(event.user_id, "Хай")
            elif request == "пока":
                write_msg(event.user_id, "Пока((")
            else:
                write_msg(event.user_id, "Не поняла вашего ответа...")


Функция write_msg получает id пользователя ВК , которому оно отправит сообщение и собственно само сообщение .

def write_msg(user_id, message):
    vk.method('messages.send', {'user_id': user_id, 'message': message})

Авторизовавшись как сообщество и настроив longpool:

# API-ключ созданный ранее
token = "6a9c267cd469388709a9e9acaddbe0aa81a0abbf12239b3e597a31729ffbddb9c88e80a443554c918b8f7"

# Авторизуемся как сообщество
vk = vk_api.VkApi(token=token)

# Работа с сообщениями
longpoll = VkLongPoll(vk)
Войдем в основной цикл:

# Основной цикл
for event in longpoll.listen():

В нем мы циклически будем проверять на наличие event-ов. А получить тип event-а сможем с помощью event.type.

После этого получив сообщение от пользователя сможем отправить ему соответствующее письмо с помощью уже созданной функции write_msg.

Итак, мы создали очень простого бота в ВК с такой же простой реализацией. А логику бота можно программировать как душе угодно.

Листинг кода в GH

Теперь приступим к более реальному программированию

Создадим класс VkBot в файле vk_bot.py, который будет служить нам ботом.

class VkBot:

    def __init__(self, user_id):
    
        print("Создан объект бота!")
        self._USER_ID = user_id
        self._USERNAME = self._get_user_name_from_vk_id(user_id)
        
        self._COMMANDS = ["ПРИВЕТ", "ПОГОДА", "ВРЕМЯ", "ПОКА"]

И добавим туда метод с помощью которого можно получить имя пользователя через vk id.

def _get_user_name_from_vk_id(self, user_id):
    request = requests.get("https://vk.com/id"+str(user_id))
    bs = bs4.BeautifulSoup(request.text, "html.parser")
    
    user_name = self._clean_all_tag_from_str(bs.findAll("title")[0])
    
    return user_name.split()[0]

Это делается с помощью beatifulsoup4.

Устанавливаем если его нет:

python -m pip install bs4

На него есть достаточное количество статей, которые стоит изучить. С помощью него же создадим еще несколько методов:

# Получение времени:
def _get_time(self):
    request = requests.get("https://my-calend.ru/date-and-time-today")
    b = bs4.BeautifulSoup(request.text, "html.parser")
    return self._clean_all_tag_from_str(str(b.select(".page")[0].findAll("h3")[1])).split()[1]

# Получение погоды
def _get_weather(city: str = "санкт-петербург") -> list:
    request = requests.get("https://sinoptik.com.ru/погода-" + city)
    b = bs4.BeautifulSoup(request.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
    
 # Метод для очистки от ненужных тэгов
 
@staticmethod
def _clean_all_tag_from_str(string_line):
    """
    Очистка строки stringLine от тэгов и их содержимых
    :param string_line: Очищаемая строка
    :return: очищенная строка
    """
    result = ""
    not_skip = True
    for i in list(string_line):
        if not_skip:
            if i == "<":
                not_skip = False
            else:
                result += i
        else:
            if i == ">":
                not_skip = True
    
    return result

Измените параметр _get_weather на нужный город, в последствии этот метод можно будет вызывать с указанием города, а по умолчанию будет ваше указанное значение.

С помощью этих методов мы сможем получить время и погоду. Эти методы вырезаны из моего основного проекта бота. Следует организовать их в отдельных пакетах и классах, применяя наследование. Но ради примера работы, я решил вместить все это в один класс бота, что конечно плохо.

Создадим основной метод new_message, который будет обрабатывать сообщение пользователя и возвращать ответ:

def new_message(self, message):

    # Привет
    if message.upper() == self._COMMANDS[0]:
        return f"Привет-привет, {self._USERNAME}!"
    
    # Погода
    elif message.upper() == self._COMMANDS[1]:
        return self._get_weather()
    
    # Время
    elif message.upper() == self._COMMANDS[2]:
        return self._get_time()
    
    # Пока
    elif message.upper() == self._COMMANDS[3]:
        return f"Пока-пока, {self._USERNAME}!"
    
    else:
        return "Не понимаю о чем вы..."

Теперь вернемся к запускаемому файлу:

Импортируем класс нашего бота:

from vk_bot import VkBot

Изменим основной наш цикл:

print("Server started")
for event in longpoll.listen():
    if event.type == VkEventType.MESSAGE_NEW:
        if event.to_me:
        
            print('New message:')
            print(f'For me by: {event.user_id}', end='')
            
            bot = VkBot(event.user_id)
            write_msg(event.user_id, bot.new_message(event.text))
            
            print('Text: ', event.text)

То есть теперь мы будем передавать полученное сообщение объекту бота, который вернет нам нужный ответ.

Это усложнение программы просто необходимо, если вы хотите дальше улучшить функционал бота:

Создайте отдельные пакеты и классы для каждой функции _get_time и _get_weather. Организуйте наследование с общего класса. И каждую новую функцию определяйте в отдельных классах, лучше всего, конечно, еще и разделить на пакеты.

Добавьте словарь с ключом идентификатора пользователя и значением объекта бота. Таким образом, не придется каждый раз в цикле создавать объект бота. К тому же, это обеспечит пользование несколькими пользователями сразу в сложных конструкциях.

Таким образом, выбрав хорошую архитектуру кода, вы сможете создать многофункционального бота.

К примеру, я научил своего бота проигрывать музыку на компьютере, открывать сайты сидя с телефона. Присылать рецепты блюд на завтрак, обед, ужин.

Вы же можете редактировать бота под себя.

Бот из статьи

Основной проект бота (улучшенный) на GH

Буду рад вашим идеям. По любым вопросам пишите.

Пишем чат бота для ВКонтакте на python с помощью longpoll / Хабр

Сейчас боты стали обыденностью и находятся на каждом шагу, но если тебе нужен свой бот в социальной сети вконтакте, то это легко реализовать.

Нам понадобятся:

  1. Python
  2. VK Api
  3. Желание

Ну прям совсем для новичков

Как установить Python?Скачиваем, запускаем установщик.

Куда писать этот код?

В текстовый документ с расширением .py

А чем писать?Да хоть блокнотом. Лично я рекомендую Notepad++

А как запускать?

Через командную строку.
python путь до папки с файлом\файл.py

Как оно работает?

Всё очень просто, в vk api есть такая штука, называется longpool работает она так:

Long Polling — это технология, которая позволяет получать данные о новых событиях с помощью «длинных запросов». Сервер получает запрос, но отправляет ответ на него не сразу, а лишь тогда, когда произойдёт какое-либо событие (например, придёт новое сообщение), либо истечёт заданное время ожидания.

Говоря русским языком, мы отправляем на сервер запрос, а он в свою очередь тыкает вконтакте если там произойдёт что либо, например, нам придёт сообщение он бежит и говорит об этом нам. От этого и будем плясать.

Техническая реализация

Для начала нам нужно доказать вконтакту что мы — это мы, а не кто-либо ещё. Делается это очень просто.

import vk_api
import requests

session = requests.Session()
login, password = 'Ваш логин, email или телефон', 'Ваш пароль'
vk_session = vk_api.VkApi(login, password)
try:
    vk_session.auth(token_only=True)
except vk_api.AuthError as error_msg:
    print(error_msg)
    return

Замечание, ребята из ВК рекомендуют использовать в качестве логина номер телефона т.к. иначе можно нарваться на проверку антиробот, ту самую где тебя просят ввести недостающие цифры из номера телефона.

Если бот будет сидеть в группе то авторизация выглядит по другому.

import requests
import vk_api

vk_session = vk_api.VkApi(token='токен с доступом к сообщениям и фото')

— Что такое токен?

— Такая штука из циферок и буковок которую нужно получить в настройках группы. Для этого достаточно открыть раздел «Управление сообществом» («Управление страницей», если у Вас публичная страница), выбрать вкладку «Работа с API» и нажать «Создать ключ доступа».

Теперь вызовем longpool.

from vk_api.longpoll import VkLongPoll, VkEventType
longpoll = VkLongPoll(vk_session)
vk = vk_session.get_api()
for event in longpoll.listen():
    if event.type == VkEventType.MESSAGE_NEW and event.to_me and event.text:
   #Слушаем longpoll, если пришло сообщение то:			
        if event.text == 'Первый вариант фразы' or event.text == 'Второй вариант фразы': #Если написали заданную фразу
            if event.from_user: #Если написали в ЛС
                vk.messages.send( #Отправляем сообщение
                    user_id=event.user_id,
                    message='Ваш текст'
		)
            elif event.from_chat: #Если написали в Беседе
                vk.messages.send( #Отправляем собщение
                    chat_id=event.chat_id,
                    message='Ваш текст'
		)

В сообщениях может быть не только заданный вами текст. Например:

import datetime
vk.messages.send(
    user_id=event.user_id,
    message='Московское время: ' + str(now.strftime("%H:%M"))
)

А ещё можно прикреплять картинки.

attachments = []
from vk_api import VkUpload 
upload = VkUpload(vk_session)
image_url = 'Ссылка на картинку'
image = session.get(image_url, stream=True)
photo = upload.photo_messages(photos=image.raw)[0]
attachments.append(
    'photo{}_{}'.format(photo['owner_id'], photo['id'])
)
vk.messages.send(
    user_id=event.user_id,
    attachment=','.join(attachments),
    message='Ваш текст'
)

Можно придумать ещё много всего интересного, но тут подумайте сами, а я лишь скажу что: ссылки можно делить на части. Например:

image_url = 'http://сайт.com/uploads/' + event.text + '.png'

и никто не запретил нам получать ответ от пользователя на примере Википедии:

import wikipedia #Модуль Википедии
wikipedia.set_lang("RU")
if event.text == 'Википедия' or event.text == 'Вики' or event.text == 'википедия' or event.text == 'вики' or event.text == 'Wikipedia' or event.text == 'wikipedia' or event.text == 'Wiki' or event.text == 'wiki': #если нам пришло сообщение с текстом Википедия или Вики или ... или wiki
    if event.from_user: #Если написали в KC
        vk.messages.send(
            user_id=event.user_id,
            message='Введите запрос' #Пишем "Введите запрос"
	)
    elif event.from_chat: #Если написали в беседе
        vk.messages.send(
            chat_id=event.chat_id,
            message='Введите запрос' #Пишем "Введите запрос"
	)
    for event in longpoll.listen():
        if event.type == VkEventType.MESSAGE_NEW and event.to_me and event.text: #Пинаем longpoll
            if event.from_user:
                vk.messages.send( #Если написали в ЛС
                    user_id=event.user_id,
                    message='Вот что я нашёл: \n' + str(wikipedia.summary(event.text)) #Пишем "Вот что я нашёл" И то что вернёт нам api Wikipedia по запросу текста сообщения
		)
                break #выходим из цикла
        elif event.from_chat: #Если написали в беседе
            vk.messages.send(
                chat_id=event.chat_id,
                message='Вот что я нашёл: \n' + str(wikipedia.summary(event.text)) #Пишем "Вот что я нашёл" И то что вернёт нам api Wikipedia по запросу текста сообщения
	    )
            break #выходим из цикла
    continue

Ссылки на примеры и документацию

Пример бота работающего на DuckDuckGo api
Примеры использования VK api (общие)
Документация по VK api Раз, Два

На этом я с вами попрощаюсь. Хорошего кодинга.

Полное руководство Python по созданию Telegram Bot с использованием python-telegram-bot

Telegram-боты — это увлечение которые позволяют вам играть в игры, находить друзей, находить новых ботов и даже создавать ботов — возможности безграничны. Сегодня я расскажу о том, как я создал telegram-бота для борьбы с пищевыми отходами, предоставляя полное учебное пособие, начиная с:

1) как создать telegram-бота с помощью BotFather

2) задавать вопросы

3) получать и хранить ответы пользователей и фотографии

4) размещать эту информацию на общедоступном Telegram-канале

5) вызов API Google Maps, чтобы показать местоположение еды на карте.

По данным продовольственно-сельскохозяйственной организации, ежегодно в мире растрачивается около 1,3 миллиарда тонн продуктов, что составляет одну треть всего продовольствия, производимого для потребления человеком. Самые распространенные виновники этой ситуации — это буфеты, рестораны и даже домашние хозяйства, по-причине закупки большого количества продуктов и не рационального их использования, превращая их в отходы даже по абсурдным причинам их внешнего вида.

В то же время 820 миллионов человек ежедневно голодают. Это кажется противоречивым — как мы можем тратить так много еды и в то же время позволить стольким людям в мире голодать? Это сводится к отсутствию связи между теми, у кого остались излишки и теми, кто нуждается в пище. Конечно, есть благотворительные организации, которые принимают пожертвования на питание, но нет прямой связи между теми, кто нуждается в еде и у того у кого продукты в избытке. В сочетании с удручающе запутанными регулирующими процессами неудивительно, что существует значительный временной промежуток между пожертвованиями продуктов питания и тем, когда они действительно приносят пользу, кто в них больше всего нуждается.

Учитывая эту проблему, почему бы не облегчить общение между теми у кого есть лишние продукты и теми, кто нуждается в еде? Это поможет связать людей с остатками пищи непосредственно с теми, кто нуждается в еде. Таким образом, пища может быть быстро получена теми, кто в ней нуждается, без значительной задержки.

Конечно, это все звучит хорошо, но как мы можем реализовать это? Именно здесь боты и каналы Telegram предоставляют простое решение для связи поставщиков продуктов питания с теми, кто нуждается в пище.

Поставщики продуктов питания могут сначала пообщаться с ботом Telegram, чтобы предоставить важную информацию о еде, такую ​​как местоположение пищи, диетические характеристики и т.д. После того, как эта информация будет собрана, бот опубликует свои списки продуктов на канале Telegram, который доступен для общественности. Как только еда размещена на канале, нуждающиеся люди могут просто забрать еду. Все это может быть выполнено без какой-либо существенной задержки — фактически весь процесс отправки еды конечному пользователю, получающему информацию, может занять менее 10 секунд!

Иллюстрированный поток процесса размещения продуктов питания

Для этого бот будет задавать следующие вопросы из поста о продуктах:

  1. Расположение еды. Используя API Карт Google, местоположение будет преобразовано в соответствующие координаты широты и долготы, которые затем могут быть отображены на карте, чтобы пользователи могли легко перемещаться к этому местоположению.
  2. Изображение еды.
  3. Диетические характеристики, то есть, является ли еда халяльной, вегетарианской и так далее.
  4. Количество порций, доступных для приема.
  5. Время, за которое еда должна быть собрана, прежде чем она будет выброшена.

Пост с едой ответит на эти вопросы, а бот соберет ответы в одно сообщение. С этим кратким сообщением бот отправит информацию общедоступному каналу после того, как автор подтвердит правильность введенных данных.

Теперь, когда у нас есть понимание того, как работает этот процесс, давайте перейдем к мельчайшим деталям!

Прежде всего, мы создадим бота. Для этого отправьте в телеграмме команду /newbot в BotFather. Он запросит у вас имя бота, а затем имя пользователя (которое должно заканчиваться на боте). Вы можете легко изменить имя бота с помощью команды /setname, но невозможно изменить имя пользователя бота через BotFather, поэтому, если вы не уверены, вы можете сначала создать тестового бота со случайным именем пользователя и после того, как вы проверили все функции и убедились, что ваш бот работает, создайте нового бота с желаемым именем пользователя.

Первое общение с BotFather — «one bot to rule them all»!

После создания бота, BotFather отправит вам ключ API бота (под строкой «Use this token to access the HTTP API:»). Держите этот ключ API у себя, потому что его может использовать любой человек с ключом API для управления вашим ботом, что для вас не желательно! Есть несколько команд, которые вы можете отправить в BotFather для настройки вашего бота, включая изменение описания бота, его профиля и т.д.

Создав нашего бота, пришло время дать ему дополнительный функционал! Поскольку цель состоит в том, чтобы создать бота, который взаимодействует с постом еды, он должен иметь возможность отправлять ему вопросы, чтобы запросить необходимую информацию, а затем сохранить информацию, прежде чем пересылать ее на общедоступный канал. Для этого мы можем использовать очень удобную оболочку Python, python-telegram-bot. На странице Github приведено множество примеров ботов, написанных с помощью оболочки, так что проверьте страницу, чтобы увидеть, есть ли примеры, подходящие для вашего варианта использования!  

Во-первых, мы установим необходимые пакеты. Поскольку мы вызываем API Карт Google для предоставления карты местоположения продуктов питания, мы также установим пакет Python googlemaps. Если вы не хотите использовать Google Maps, вы можете пропустить установку этого пакета.

В вашем терминале / командной строке введите следующие команды для установки двух библиотек:

pip install python-telegram-bot # using version 12.7
pip install googlemaps # using version 4.3.1

Теперь, когда мы установили две библиотеки, давайте погрузимся в код! Вот код (на случай, если вы захотите перейти прямо к нему), который я подробно покажу ниже.

Полный код бота Telegram, включая вызов в Google Maps API

"""
telegrambot.py
Starter code to create a telegram bot using the python-telegram-bot library.
Includes call to Google Maps API to extract map coordinates from location.
Author: liuhh02 https://medium.com/@liuhh02
"""

import logging
import telegram
from telegram import (ReplyKeyboardMarkup, ReplyKeyboardRemove)
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters,
                          ConversationHandler)
from googlemaps import Client as GoogleMaps
import os

# Включить ведение журнала
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)

LOCATION, PHOTO, DIET, SERVINGS, TIME, CONFIRMATION = range(6)

reply_keyboard = [['Confirm', 'Restart']]
markup = ReplyKeyboardMarkup(reply_keyboard, resize_keyboard=True, one_time_keyboard=True)
TOKEN = 'YOURTELEGRAMBOTTOKEN'
bot = telegram.Bot(token=TOKEN)
chat_id = 'YOURTELEGRAMCHANNEL'
GMAPSAPI = 'YOURGOOGLEMAPSAPITOKEN'
gmaps = GoogleMaps(GMAPSAPI)

PORT = int(os.environ.get('PORT', 5000))

def facts_to_str(user_data):
    facts = list()

    for key, value in user_data.items():
        facts.append('{} - {}'.format(key, value))

    return "\n".join(facts).join(['\n', '\n'])


def start(update, context):
    update.message.reply_text(
        "Hi! I am your posting assistant to help you advertise your leftover food to reduce food waste. "
        "To start, please type the location of the leftover food.")
    return LOCATION


def location(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Location'
    text = update.message.text
    user_data[category] = text
    logger.info("Location of %s: %s", user.first_name, update.message.text)

    update.message.reply_text('I see! Please send a photo of the leftovers, '
                              'so users will know how the food looks like, or send /skip if you don\'t want to.')
    return PHOTO


def photo(update, context):
    user = update.message.from_user
    user_data = context.user_data
    photo_file = update.message.photo[-1].get_file()
    photo_file.download('user_photo.jpg')
    category = 'Photo Provided'
    user_data[category] = 'Yes'
    logger.info("Photo of %s: %s", user.first_name, 'user_photo.jpg')
    update.message.reply_text('Great! Is the food halal? Vegetarian? Please type in the dietary specifications of the food.')

    return DIET


def skip_photo(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Photo Provided'
    user_data[category] = 'No'
    logger.info("User %s did not send a photo.", user.first_name)
    update.message.reply_text('Is the food halal? Vegetarian? Please type in the dietary specifications of the food.')

    return DIET


def diet(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Dietary Specifications'
    text = update.message.text
    user_data[category] = text
    logger.info("Dietary Specification of food: %s", update.message.text)
    update.message.reply_text('How many servings are there?')

    return SERVINGS

def servings(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Number of Servings'
    text = update.message.text
    user_data[category] = text
    logger.info("Number of servings: %s", update.message.text)
    update.message.reply_text('What time will the food be available until?')

    return TIME
    
def time(update, context):
	user = update.message.from_user
	user_data = context.user_data
	category = 'Time to Take Food By'
	text = update.message.text
	user_data[category] = text
	logger.info("Time to Take Food By: %s", update.message.text)
	update.message.reply_text("Thank you for providing the information! Please check the information is correct:"
								"{}".format(facts_to_str(user_data)), reply_markup=markup)

	return CONFIRMATION

def confirmation(update, context):
    user_data = context.user_data
    user = update.message.from_user
    update.message.reply_text("Thank you! I will post the information on the channel @" + chat_id + "  now.", reply_markup=ReplyKeyboardRemove())
    if (user_data['Photo Provided'] == 'Yes'):
        del user_data['Photo Provided']
        bot.send_photo(chat_id=chat_id, photo=open('user_photo.jpg', 'rb'), 
		caption="<b>Food is Available!</b> Check the details below: \n {}".format(facts_to_str(user_data)) +
		"\n For more information, message the poster {}".format(user.name), parse_mode=telegram.ParseMode.HTML)
    else:
        del user_data['Photo Provided']
        bot.sendMessage(chat_id=chat_id, 
            text="<b>Food is Available!</b> Check the details below: \n {}".format(facts_to_str(user_data)) +
        "\n For more information, message the poster {}".format(user.name), parse_mode=telegram.ParseMode.HTML)
    geocode_result = gmaps.geocode(user_data['Location'])
    lat = geocode_result[0]['geometry']['location'] ['lat']
    lng = geocode_result[0]['geometry']['location']['lng']
    bot.send_location(chat_id=chat_id, latitude=lat, longitude=lng)

    return ConversationHandler.END

def cancel(update, context):
    user = update.message.from_user
    logger.info("User %s canceled the conversation.", user.first_name)
    update.message.reply_text('Bye! Hope to see you again next time.',
                              reply_markup=ReplyKeyboardRemove())

    return ConversationHandler.END


def error(update, context):
    """Log Errors caused by Updates."""
    logger.warning('Update "%s" caused error "%s"', update, context.error)


def main():
    # Создайте программу обновления и передайте ей токен вашего бота.
    # Убедитесь, что use_context=true используется для новых условиях на основе обратных вызовов
    # Пост версия12 в этом больше не будет необходимости
    updater = Updater(TOKEN, use_context=True)

    # Пусть диспетчер зарегистрирует обработчиков
    dp = updater.dispatcher

    # Добавьте обработчик разговоров с состояниями пол, фото, местонахождение и биография
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],

        states={

            LOCATION: [CommandHandler('start', start), MessageHandler(Filters.text, location)],

            PHOTO: [CommandHandler('start', start), MessageHandler(Filters.photo, photo),
                    CommandHandler('skip', skip_photo)],

            DIET: [CommandHandler('start', start), MessageHandler(Filters.text, diet)],

            SERVINGS: [CommandHandler('start', start), MessageHandler(Filters.text, servings)],

            TIME: [CommandHandler('start', start), MessageHandler(Filters.text, time)],

            CONFIRMATION: [MessageHandler(Filters.regex('^Confirm$'),
                                      confirmation),
            MessageHandler(Filters.regex('^Restart$'),
                                      start)
                       ]

        },

        fallbacks=[CommandHandler('cancel', cancel)]
    )

    dp.add_handler(conv_handler)

    # лог всех ошибок
    dp.add_error_handler(error)

    updater.start_webhook(listen="0.0.0.0", port=int(PORT), url_path=TOKEN)
    updater.bot.setWebhook('https://YOURHEROKUAPPNAME.herokuapp.com/' + TOKEN)

    # Запускайте бота до тех пор, пока вы не нажмете Ctrl-C или процесс не получит SIGINT,
    # SIGTERM или SIGABRT. Это следует использовать большую часть времени, так как
    # start_polling() является неблокирующим и остановит бота.
    updater.idle()


if __name__ == '__main__':
    main()

Во-первых, мы импортируем соответствующие библиотеки:

import logging
import telegram
from telegram import (ReplyKeyboardMarkup, ReplyKeyboardRemove)
from telegram.ext import (Updater, CommandHandler, MessageHandler,  Filters, ConversationHandler)
from googlemaps import Client as GoogleMaps

Мы импортируем логи, чтобы показать сообщения, когда пользователь находится в терминале и когда он взаимодействует с ботом, а также различные модули под python-telegram-bot. Мы также импортируем googlemaps, чтобы показать местоположение еды на карте.

Далее мы настраиваем параметры ведения журнала следующим образом:

# Включить ведение журнала
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) 
logger = logging.getLogger(__name__)

Далее мы определяем шесть пунктов, которые определяют вопросы, которые будет задавать бот: местоположение еды, фото, диетические характеристики, количество порций, время сбора еды, а также подтверждение с постом.

LOCATION, PHOTO, DIET, SERVINGS, TIME, CONFIRMATION = range(6)

Для подтверждения появится клавиатура с ответами, где пользователь сможет выбрать два варианта: подтвердить правильность информации или перезапустить весь процесс.

Кнопка подтверждения и перезагрузки

Итак, мы указываем две опции, используя модуль ReplyKeyboardMarkup в модуле python-telegram-bot, используя следующую строку кода:

reply_keyboard = [['Confirm', 'Restart']]
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)

После этого мы указываем некоторые переменные, включая API вашего бота Telegram (который вы получили от BotFather), а также API Google Maps.

Чтобы получить API Карт Google, вам потребуется аккаунт Google Cloud Platform. После создания учетной записи (будут предоставлены бесплатные кредиты, поэтому она должна быть бесплатной, если вы не превышаете квоту), перейдите в консоль Google Cloud Platform и выполните следующие действия:  

  1. Поиск API и услуг в строке поиска.
  2. Нажмите синюю кнопку «plus » с надписью «ENABLE APIS AND SERVICES» прямо под строкой поиска
  3. Найдите API геокодирования и включите его.
  4. В разделе « API & Services» перейдите в раздел «Credentials» и выберите «CREATE CREDENTIALS» > API key.

Будет сгенерирован ключ API, поэтому просто скопируйте его. Это будет ваш токен API карт Google. Опять же, держите его в безопасности! API геокодирования предоставляет 200 долларов в кредит, так что этого будет достаточно для ваших целей.

TOKEN = 'YOURTELEGRAMBOTTOKEN'
bot = telegram.Bot(token=TOKEN) 
GMAPSAPI = 'YOURGOOGLEMAPSAPITOKEN'
gmaps = GoogleMaps(GMAPSAPI)

Теперь, когда мы определили переменные, давайте углубимся в фактическую часть кода! Во-первых, мы определяем функцию для суммирования информации, представленной рекламным постом, как показано ниже:

def facts_to_str(user_data):
    facts = list()
    for key, value in user_data.items():
        facts.append('{} - {}'.format(key, value))
    return "\n".join(facts).join(['\n', '\n'])

Когда эта функция вызывается, она возвращает информацию в формате ключ-значение (например, Dietary Specifications — Halal).

Далее мы определяем, что происходит, когда пользователь запускает бота. Это делается с помощью команды /start (она работает аналогично тому, как вы использовали команду /newbot с BotFather для создания своего бота). Когда пост запускает бота, мы хотим, чтобы бот приветствовал пользователя и предложил ему отправить местоположение еды, поэтому мы определяем начало следующим образом:

def start(update, context):
    update.message.reply_text("Hi! I am your posting assistant to help you advertise your leftover food to reduce food waste. To start, please type the location of the leftover food.")
    return LOCATION

Предыдущая функция возвращает LOCATION, которая является следующей функцией, потому что бот сохранит местоположение, предоставленное пользователем, для создания сводки в конце. В расположении функции, код делает несколько вещей: во-первых он говорит боту, что есть новое сообщение от пользователя, а затем хранит информацию предоставленную пользователем под ключ «Location» для удобства при печати резюме. Затем он регистрирует информацию для целей отладки, на случай, если что-то пойдет не так. Наконец, бот отвечает сообщением с просьбой сфотографировать еду. Затем он возвращает PHOTO, которое является следующей функцией.

def location(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Location'
    text = update.message.text
    user_data[category] = text
    logger.info("Location of %s: %s", user.first_name, update.message.text)
    update.message.reply_text('I see! Please send a photo of the leftovers, so users will know how the food looks like, or send /skip if you don\'t want to.')
     return PHOTO

В этой следующей функции у пользователя есть два варианта: либо сфотографировать еду и отправить ее боту, либо пропустить, если у него нет готового изображения.

def photo(update, context):
    user = update.message.from_user
    photo_file = update.message.photo[-1].get_file()
    photo_file.download('user_photo.jpg')
    logger.info("Photo of %s: %s", user.first_name, 'user_photo.jpg')
    update.message.reply_text('Great! Is the food halal? Vegetarian? Please type in the dietary specifications of the food.')
     return DIET 
def skip_photo(update, context):
    user = update.message.from_user
    logger.info("User %s did not send a photo.", user.first_name)
    update.message.reply_text('Is the food halal? Vegetarian? Please type in the dietary specifications of the food.')
    return DIET

Опять же, бот сначала получает сообщение от пользователя, а затем получает от него файл фотографии, который затем сохраняется как user_photo.jpg. Затем он регистрирует информацию, и бот отвечает следующим вопросом о диетических характеристиках пищи.

Следующие строки следуют той же структуре, что и раньше, поскольку бот спрашивает о диетических спецификациях, количестве порций, времени для сбора пищи. Вы заметите ту же структуру: бот сначала получает сообщение от пользователя, затем пользовательский ответ сохраняется в user_data, затем ведется протоколирование, а затем ответ от бота, чтобы предложить ему следующий вопрос.

def diet(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Dietary Specifications'
    text = update.message.text
    user_data[category] = text
    logger.info("Dietary Specification of food: %s", update.message.text)
    update.message.reply_text('How many servings are there?')
    return SERVINGS 
def servings(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Number of Servings'
    text = update.message.text
    user_data[category] = text
    logger.info("Number of servings: %s", update.message.text)    update.message.reply_text('What time will the food be available until?')
     return TIME
def time(update, context):
    user = update.message.from_user
    user_data = context.user_data
    category = 'Time to Take Food By'
    text = update.message.text
    user_data[category] = text
    logger.info("Time to Take Food By: %s", update.message.text) 
    update.message.reply_text("Thank you for providing the information! Please check the information is correct:{}".format(facts_to_str(user_data)), reply_markup=markup)
    return CONFIRMATION

Получив всю необходимую информацию, настало время ее обобщить и подтвердить с помощью поста. Во-первых, бот объединяет информацию, а затем отправляет сводку, используя функцию fact_to_str (user_data), которую мы определили выше.

Если пользователь выберет «Confirm», бот отправит информацию на общедоступный канал. Параметр chat_id файла bot.send_photo представляет ссылку канала.

def confirmation(update, context):
    user_data = context.user_data
    user = update.message.from_user
    update.message.reply_text("Thank you! I will post the information on the channel now.", reply_markup=ReplyKeyboardRemove())
    bot.send_photo(chat_id='@nameofchannel', photo=open('user_photo.jpg', 'rb'), caption="<b>Food is Available!</b> Check the details below: \n {}".format(facts_to_str(user_data)) +  "\n For more information, message the poster {}".format(user.name), parse_mode=telegram.ParseMode.HTML)
    geocode_result = gmaps.geocode(user_data['Location'])
    lat = geocode_result[0]['geometry']['location'] ['lat']
    lng = geocode_result[0]['geometry']['location']['lng']
    bot.send_location(chat_id='@nameofchannel', latitude=lat, longitude=lng)

Кроме того, теперь мы обращаемся к картам Google, чтобы точно определить местоположение, указанное на плакате. Местоположение было сохранено в user_data [‘Location’] ранее, когда пользователь ответил на первый вопрос о нем, поэтому теперь мы будем извлекать широту и долготу, используя карты Google. Получив эту информацию, бот отправляет данные о местоположении вместе с картой на канал, указанный в @nameofchannel.

Вот некоторые вспомогательные функции на случай, если пользователь отменит разговор с ботом или возникнет ошибка:

def cancel(update, context):
    user = update.message.from_user
    logger.info("User %s canceled the conversation.", user.first_name)
    update.message.reply_text('Bye! Hope to see you again next time.', reply_markup=ReplyKeyboardRemove())
     return ConversationHandler.END
def error(update, context):
    """Log Errors caused by Updates."""
    logger.warning('Update "%s" caused error "%s"', update, context.error)

Мы находимся в последнем сегменте кода! Здесь код определяет, что бот должен делать для каждого из шести пунктов. Наконец, мы начинаем опрос, который в основном позволяет нам получать информацию с постов. GitHub wiki python-telegram-bot лучше объясняет код здесь, так что проверьте его, если вы не уверены, что делает каждая строка!

#!/usr/bin/python
# -- coding: utf-8 --


def main():
    updater = Updater(TOKEN, use_context=True)

     # Пусть диспетчер зарегистрирует обработчиков
    dp = updater.dispatcher

     # Добавьте обработчик разговоров с состояниями LOCATION, PHOTO, DIET, SERVINGS, TIME and DONE

    conv_handler = \
        ConversationHandler(entry_points=[CommandHandler('start',
                            start)], states={
        LOCATION: [MessageHandler(Filters.text, location)],
        PHOTO: [MessageHandler(Filters.photo, photo),
                CommandHandler('skip', skip_photo)],
        DIET: [MessageHandler(Filters.text, location)],
        SERVINGS: [MessageHandler(Filters.text, bio)],
        TIME: [MessageHandler(Filters.text, time)],
        CONFIRMATION: [MessageHandler(Filters.regex('^Confirm$'),
                       done), MessageHandler(Filters.regex('^Restart$'
                       ), start)],
        }, fallbacks=[CommandHandler('cancel', cancel),
                      CommandHandler('start', start)])
    dp.add_handler(conv_handler)  # log all errors
    dp.add_error_handler(error)

    # Запускаем бота

    updater.start_polling()

    # Запускайте бота, нажмете кнопку Ctrl-C

    updater.idle()


if _name_ == '_main_':
    main()

Чтобы запустить своего бота, просто перейдите в terminal/command и запустите файл python. После выполнения файла перейдите к боту и введите /start. Ваш бот должен ответить и задать вам вопросы, как написано выше! Когда вы отвечаете, вы также должны увидеть следующие журналы:

Регистрация ответа автора, как видно из командной строки

Итак, это все! 

Пишем бота для Instagram на Python

Чтобы охватить большую аудиторию в Instagram, получить больше лайков и новых подписчиков, мы обращаемся за помощью к специалистам: SocialCaptain, Kicksta, Instavast и другим компаниям. У них есть автоматизированные инструменты, которые делают за вас всю работу. За это мы платим большие деньги – но то же самое можно получить бесплатно, используя InstaPy.

Мы напишем бота на Python, который автоматизирует ваши действия в Instagram. В результате вы получите больше лайков и подписчиков с минимальными усилиями. Параллельно разберемся в автоматизации браузера, работе Selenium и шаблона Page Object, лежащих в основе InstaPy.

Политика Instagram

Убедитесь, что вы ознакомились с Политикой предоставления услуг Instagram, прежде чем начинать работу.

Прежде чем начинать автоматизировать что-либо, давайте подумаем, как получает лайки и подписки в Instagram реальный пользователь?

За счет активности. Человек размещает посты, просматривает ленту, лайкает и комментирует посты других людей. Боты делают то же самое, но не тратя ваше время. Вы лишь устанавливаете критерии выбора.

Очень важны настройки бота, ведь от них напрямую зависят результаты, которые вы получите. Важно отобрать те профили, владельцам которых будет интересен ваш контент. Например, если вы продаете в Instagram женскую одежду, будет разумно научить бота отслеживать женские аккаунты, а также посты с хештегами #красота, #мода, #одежда. Это повысит вероятность того, что ваш профиль будет замечен целевой аудиторией.

Но как реализовать это технически? Instagram Developer API ограничен и не подойдет для наших целей. Следует обратиться к браузерной автоматизации.

Это работает очень просто:

  1. Вы указываете свои учетные данные.
  2. Устанавливаете критерии для отбора профилей и постов, а также настройки для комментариев.
  3. Бот открывает браузер, переходит на сайт, авторизуется с вашими данными и начинает выполнять полученные инструкции.

Давайте перейдем к практике. Для начала напишем бота, который сможет самостоятельно зайти в ваш Instagram-профиль.

Для первой версии бота будем использовать Selenium – инструмент, работающий под капотом InstaPy, к которому мы перейдем чуть позже.

Для начала установите сам Selenium. Убедитесь, что на вашем компьютере установлен браузер Firefox и Firefox WebDriver. Мы будем работать с этим браузером, так как в последней версии InstaPy нет поддержки Chrome.

Для работы Selenium вам также может понадобиться установить geckodriver.

1. Открываем браузер

Создайте файл с расширением .py и вставьте туда следующий код:

instabot.py

        from time import sleep
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.instagram.com/')
sleep(5)
browser.close()
    

Сначала мы импортируем нужные пакеты. Затем инициализируется драйвер Firefox и запускается браузер. Бот набирает в адресной строке адрес https://www.instagram.com/ – открывается страница авторизации Instagram. Через 5 секунд ожидания браузер закрывается. Запустите код и проверьте, как он работает. Только что мы написали в своем роде «Hello world» на Selenium.

2. Открываем страницу авторизации

Добавим авторизацию. Для начала составим пошаговый алгоритм действий:

  1. Перейти на страницу https://www.instagram.com/.
  2. Нажать ссылку Авторизоваться.
  3. Ввести логин и пароль.
  4. Нажать на кнопку Log In ( Войти).

Примечание

Если по адресу https://www.instagram.com/ сразу открывается страница авторизации и нет ссылок с текстом (Log in/Авторизоваться), просто пропустите этот шаг.

Первый пункт мы уже выполнили. Давайте теперь найдем на странице ссылку для авторизации и кликнем по ней:

instabot.py

        from time import sleep
from selenium import webdriver

browser = webdriver.Firefox()
browser.implicitly_wait(5) # устанавливаем пятисекундную задержку
# Если Selenium не может найти элемент, он ждет, чтобы все загрузилось и пытается снова

browser.get('https://www.instagram.com/')

# Следующие строки говорят боту найти ссылку с текстом Log in и кликнуть по ней. 
login_link = browser.find_element_by_xpath("//a[text()='Log in']")  
login_link.click()

sleep(5)

browser.close()
    

Мы используем для поиска нужной ссылки XPath, но есть и другие методы.

Запустите скрипт и убедитесь, что он работает. В браузере должна открыться страница авторизации.

3. Заполнение формы

В форме авторизации – три важных элемента:

  • Поле для введения логина;
  • Поле для пароля;
  • Кнопка Войти.

Давайте найдем их, введем учетные данные и залогинимся:

instabot.py

        from time import sleep
from selenium import webdriver

browser = webdriver.Firefox()
browser.implicitly_wait(5)

browser.get('https://www.instagram.com/')

login_link = browser.find_element_by_xpath("//a[text()='Log in']")
login_link.click()

sleep(2)

username_input = browser.find_element_by_css_selector("input[name='username']")
password_input = browser.find_element_by_css_selector("input[name='password']")

username_input.send_keys("<имя пользователя>")
password_input.send_keys("<пароль>")

login_button = browser.find_element_by_xpath("//button[@type='submit']")
login_button.click()

sleep(5)

browser.close()
    

Устанавливаем двухсекундную задержку для загрузки страницы. Находим и заполняем нужные поля. В конце ищем и нажимаем кнопку для входа.

Если вы укажете правильные данные и запустите этот скрипт, он самостоятельно авторизуется в вашем Instagram аккаунте.

***

Мы отлично начали, и при желании легко можем продолжить создавать бота. Дальнейшие действия очень похожи на уже сделанные: прокручиваем ленту вниз, ищем интересные посты по определенным критериями, ищем кнопку для лайка и нажимаем на нее, ищем раздел с комментариями и т. д.

Хорошая новость – все эти шаги за вас может сделать InstaPy. Но прежде чем мы начнем с ним работать, давайте разберемся в основах – паттерне Page Object.

Мы написали код для авторизации – но как теперь его тестировать ? Это могло бы выглядеть как-то так:

        def test_login_page(browser):
    browser.get('https://www.instagram.com/accounts/login/')
    username_input = browser.find_element_by_css_selector("input[name='username']")
    password_input = browser.find_element_by_css_selector("input[name='password']")
    username_input.send_keys("<your username>")
    password_input.send_keys("<your password>")
    login_button = browser.find_element_by_xpath("//button[@type='submit']")
    login_button.click()

    errors = browser.find_elements_by_css_selector('#error_message')
    assert len(errors) == 0
    

Что не так с этим кодом? Он не соответствует принципу DRY и идеям чистого кода: одни и те же фрагменты дублируются и в приложении, и в тесте.

В этом контексте дублирование кода особенно плохо, так как Selenium зависит от элементов пользовательского интерфейса, а они имеют тенденцию меняться. Если это происходит, хотелось бы вносить изменения только в одном месте, а не в десятке. Здесь и приходит на помощь шаблон Page Object.

С помощью этого шаблона вы создаете классы page objects для наиболее важных страниц или фрагментов страницы, которые предоставляют удобные интерфейсы для взаимодействия.

Мы можем отрефакторить наш код и создать класс HomePage и класс LoginPage:

pages.py

        from time import sleep

class LoginPage:
    def __init__(self, browser):
        self.browser = browser

    def login(self, username, password):
        username_input = self.browser.find_element_by_css_selector("input[name='username']")
        password_input = self.browser.find_element_by_css_selector("input[name='password']")
        username_input.send_keys(username)
        password_input.send_keys(password)
        login_button = browser.find_element_by_xpath("//button[@type='submit']")
        login_button.click()
        sleep(5)

class HomePage:
    def __init__(self, browser):
        self.browser = browser
        self.browser.get('https://www.instagram.com/')

    def go_to_login_page(self):
        self.browser.find_element_by_xpath("//a[text()='Log in']").click()
        sleep(2)
        return LoginPage(self.browser)
    

Логика осталась без изменений, только теперь домашняя страница и страница входа представлены в виде классов. Они инкапсулируют все действия, необходимые для поиска и обработки данных в пользовательском интерфейсе.

Обратите внимание, при переходе на другую страницу с помощью метода объекта страницы, возвращается новый объект страницы. Взгляните на возвращаемое значение функции go_to_log_in_page().

Если бы у нас уже был класс FeedPage, то метод login() класса LoginPage вернул бы экземпляр страницы фида (return FeedPage()).

Изменим основной код:

instabot.py

        from selenium import webdriver
from pages import HomePage

browser = webdriver.Firefox()
browser.implicitly_wait(5)

home_page = HomePage(browser)
login_page = home_page.go_to_login_page()
login_page.login("<your username>", "<your password>")

browser.close()
    

Теперь программа выглядит намного проще и понятнее. Тесты тоже можно переписать:

        def test_login_page(browser):
    home_page = HomePage(browser)
    login_page = home_page.go_to_login_page()
    login_page.login("<your username>", "<your password>")

    errors = browser.find_elements_by_css_selector('#error_message')
    assert len(errors) == 0
    

Если в интерфейсе что-то изменится, не придется менять тесты – и это правильно.

Чтобы узнать больше о шаблоне Page Object, обратитесь к официальной документации и статье Мартина Фаулера.

А мы переходим к созданию бота версии 2.0 – с помощью InstaPy.

Для начала установим InstaPy:

        $ python3 -m pip install instapy

    

Виртуальные среды

Авторизация в Instagram

Перепишем код с использованием InstaPy:

instabot2.py

        from instapy import InstaPy

InstaPy(username="<your_username>", password="<your_password>").login()
    

Подставьте правильный логин и пароль и запустите скрипт. Вуаля! Одна строчка кода – а результат тот же самый!

На самом деле, не тот же самый. Instapy выполняет множество других действий: проверяет интернет-соединение, состояние серверов Instagram и пр. Все это вы можете наблюдать напрямую в браузере, а также в логах.

        INFO [2019-12-17 22:03:19] [username]  -- Connection Checklist [1/3] (Internet Connection Status)
INFO [2019-12-17 22:03:20] [username]  - Internet Connection Status: ok
INFO [2019-12-17 22:03:20] [username]  - Current IP is "17.283.46.379" and it's from "Germany/DE"
INFO [2019-12-17 22:03:20] [username]  -- Connection Checklist [2/3] (Instagram Server Status)
INFO [2019-12-17 22:03:26] [username]  - Instagram WebSite Status: Currently Up
    

Неплохо для одной строки кода, правда? Переходим к решительным действиям!

Основные настройки бота

Предположим, что ваш профиль посвящен автомобилям. Вы хотите, чтобы бот взаимодействовал с профилями людей, интересующихся автомобилями.

Лайки

Например, бот может лайкать посты с хештегами #bmw или #mercedes. Для этого предназначен метод like_by_tags():

instabot2.py

        from instapy import InstaPy

session = InstaPy(username="<your_username>", password="<your_password>")
session.login()
session.like_by_tags(["bmw", "mercedes"], amount=5) # [1]
    

Мы передаем методу массив тегов, которые нужно лайкнуть, и количество постов для каждого тега. Другими словами, бот должен поставить 10 лайков – по пять для каждого из двух тегов.

Но взгляните, что происходит в логах после запуска скрипта:

        INFO [2019-12-17 22:15:58] [username]  Tag [1/2]
INFO [2019-12-17 22:15:58] [username]  --> b'bmw'
INFO [2019-12-17 22:16:07] [username]  desired amount: 14  |  top posts [disabled]: 9  |  possible posts: 43726739
INFO [2019-12-17 22:16:13] [username]  Like# [1/14]
INFO [2019-12-17 22:16:13] [username]  https://www.instagram.com/p/B6MCcGcC3tU/
INFO [2019-12-17 22:16:15] [username]  Image from: b'mattyproduction'
INFO [2019-12-17 22:16:15] [username]  Link: b'https://www.instagram.com/p/B6MCcGcC3tU/'
INFO [2019-12-17 22:16:15] [username]  Description: b'Mal etwas anderes \xf0\x9f\x91\x80\xe2\x98\xba\xef\xb8\x8f Bald ist das komplette Video auf YouTube zu finden (n\xc3\xa4here Infos werden folgen). Vielen Dank an @patrick_jwki @thehuthlife  und @christic_  f\xc3\xbcr das bereitstellen der Autos \xf0\x9f\x94\xa5\xf0\x9f\x98\x8d#carporn#cars#tuning#bagged#bmw#m2#m2competition#focusrs#ford#mk3#e92#m3#panasonic#cinematic#gh5s#dji#roninm#adobe#videography#music#bimmer#fordperformance#night#shooting#'
INFO [2019-12-17 22:16:15] [username]  Location: b'K\xc3\xb6ln, Germany'
INFO [2019-12-17 22:16:51] [username]  --> Image Liked!
INFO [2019-12-17 22:16:56] [username]  --> Not commented
INFO [2019-12-17 22:16:57] [username]  --> Not following
INFO [2019-12-17 22:16:58] [username]  Like# [2/14]
INFO [2019-12-17 22:16:58] [username]  https://www.instagram.com/p/B6MDK1wJ-Kb/
INFO [2019-12-17 22:17:01] [username]  Image from: b'davs0'
INFO [2019-12-17 22:17:01] [username]  Link: b'https://www.instagram.com/p/B6MDK1wJ-Kb/'
INFO [2019-12-17 22:17:01] [username]  Description: b'Someone said cloud? \xf0\x9f\xa4\x94\xf0\x9f\xa4\xad\xf0\x9f\x98\x88 \xe2\x80\xa2\n\xe2\x80\xa2\n\xe2\x80\xa2\n\xe2\x80\xa2\n#bmw #bmwrepost #bmwm4 #bmwm4gts #f82 #bmwmrepost #bmwmsport #bmwmperformance #bmwmpower #bmwm4cs #austinyellow #davs0 #mpower_official #bmw_world_ua #bimmerworld #bmwfans #bmwfamily #bimmers #bmwpost #ultimatedrivingmachine #bmwgang #m3f80 #m5f90 #m4f82 #bmwmafia #bmwcrew #bmwlifestyle'
INFO [2019-12-17 22:17:34] [username]  --> Image Liked!
INFO [2019-12-17 22:17:37] [username]  --> Not commented
INFO [2019-12-17 22:17:38] [username]  --> Not following
    

По умолчанию InstaPy будет лайкать первые девять постов в ленте к дополнению к параметру amount. В этом случае общее количество лайков – 14 на один тег (9 + 5).

InstaPy регистрирует каждое действие: упоминает, какой пост ему понравился, ссылку на него, описание, местоположение, указывает, комментировал ли и подписался ли на аккаунт.

Возможно, вы заметили, что почти после каждого действия возникают задержки. Это сделано специально, чтобы Instagram не забанил ваш профиль.

Вы также можете указать параметры постов, которые бот НЕ должен лайкать, с помощью метода set_dont_like():

instabot2.py

        from instapy import InstaPy

session = InstaPy(username="<your_username>", password="<your_password>")
session.login()
session.like_by_tags(["bmw", "mercedes"], amount=5)
session.set_dont_like(["naked", "nsfw"])
    

Теперь бот будет игнорировать посты, в описании которых есть слова «naked» или «nsfw» (not safe/suitable for work).

Подписки

Кроме лайков бот умеет подписываться на аккаунты. Для этого предназначена функция set_do_follow():

instabot2.py

        from instapy import InstaPy

session = InstaPy(username="<your_username>", password="<your_password>")
session.login()
session.like_by_tags(["bmw", "mercedes"], amount=5)
session.set_dont_like(["naked", "nsfw"])
session.set_do_follow(True, percentage=50)
    

Если вы запустите этот скрипт, то бот подпишется на 50% от тех юзеров, чьи посты он лайкнул. Опять же каждое действие будет залогировано.

Комментарии

Еще одна опция InstaPy – возможность оставлять комментарии. Для этого нужно сделать две вещи. Сначала разрешите комментирование вызовом метода set_do_comment():

instabot2.py

        from instapy import InstaPy

session = InstaPy(username="<your_username>", password="<your_password>")
session.login()
session.like_by_tags(["bmw", "mercedes"], amount=5)
session.set_dont_like(["naked", "nsfw"])
session.set_do_follow(True, percentage=50)
session.set_do_comment(True, percentage=50)
    

Затем укажите, что именно писать с помощью set_comments():

instabot2.py

        from instapy import InstaPy

session = InstaPy(username="<your_username>", password="<your_password>")
session.login()
session.like_by_tags(["bmw", "mercedes"], amount=5)
session.set_dont_like(["naked", "nsfw"])
session.set_do_follow(True, percentage=50)
session.set_do_comment(True, percentage=50)
session.set_comments(["Nice!", "Sweet!", "Beautiful :heart_eyes:"])
    

Запустите скрипт, и бот оставит один из трех указанных комментариев под половиной постов, с которыми он взаимодействовал.

Закрытие сессии

После того, как вы сделали все, что хотели, нужно закрыть сессию, вызвав метод end():

instabot2.py

        from instapy import InstaPy

session = InstaPy(username="<your_username>", password="<your_password>")
session.login()
session.like_by_tags(["bmw", "mercedes"], amount=5)
session.set_dont_like(["naked", "nsfw"])
session.set_do_follow(True, percentage=50)
session.set_do_comment(True, percentage=50)
session.set_comments(["Nice!", "Sweet!", "Beautiful :heart_eyes:"])
session.end()
    

Эта команда закроет браузер, сохранит логи и подготовит отчет, который вы можете увидеть в консоли.

Дополнительные возможности InstaPy

InstaPy – это большой проект, который имеет множество тщательно документированных функций. Рассмотрим несколько наиболее полезных из них.

Квоты

Нельзя скрейпить Instagram целыми днями, сервис быстро это заметит. Поэтому полезно установить квоты на действия бота.

        session.set_quota_supervisor(enabled=True, peak_comments_daily=240, peak_comments_hourly=21)

    

Этот код ограничивает пределы комментирования за час и за целый день. Когда бот достигнет их, он перестанет комментировать и будет ждать истечения периода квоты.

Аргумент headless_browser

Указанный в названии аргумент позволяет запускать бота без графического интерфейса браузера. Она полезна, если вы хотите развернуть бота на сервере, где нет или не нужен интерфейс. Производительность в таком режиме выше, так как меньше нагрузка на процессор.

        session = InstaPy(username='test', password='test', headless_browser=True)

    

Обратите внимание, соответствующий флаг устанавливается при инициализации объекта InstaPy.

Искусственный интеллект для анализа сообщений

Мы уже научились игнорировать сообщения, в которых содержатся неуместные слова. А что делать, если описание нормальное, но сама картинка неуместна?

InstaPy-бот можно интегрировать с ClarifApi – инструментом для распознавания изображений и видео:

        session.set_use_clarifai(enabled=True, api_key='<your_api_key>')
session.clarifai_check_img_for(['nsfw'])
    

Теперь бот будет игнорировать любое изображение, которое ClarifApi посчитает NSFW. 5000 обращений в месяц – бесплатно.

Количество подписчиков

Зачастую не имеет смысла взаимодействовать с аккаунтами с большим количеством подписчиков. InstaPy дает возможность установить границы для этого количества, чтобы бот не тратил впустую вычислительные ресурсы вашей машины:

        session.set_relationship_bounds(enabled=True, max_followers=8500)

    

Теперь бот не будет взаимодействовать с постами пользователей, у которых больше 8,5 тысяч подписчиков.

Множество других опций и конфигураций вы можете найти в документации InstaPy.

***

InstaPy – гибкий инструмент, который позволяет легко и быстро автоматизировать действия пользователя в Instagram. Его работа основана на браузерной автоматизации (Selenium) и использовании шаблона Page Object для облегчения работы с веб-страницами.

Если вы еще не начали писать код, прочитайте нашу публикацию о том, как создать виртуальное окружение в Python. Это позволит избежать проблем с зависимостями пакетом. Мы также писали о том, как работает распознавание объектов в реальном времен – впоследствии бота можно улучшить, если привлечь собственную модель для анализа фотографий пользователей.

Как написать telegram-бота на python с помощью библиотеки telebot

Как написать telegram-бота на python с помощью библиотеки telebot

Установка и настройка

Для начала давайте скачаем сам python. Сделать это можно на официальном сайте. Не забудьте поставить галочку add to PATH во время установки! После установки python’a нам понадобится хороший редактор кода. На помощь приходит компания JetBrains со своим бесплатным PyCharm. Мы уже близко, осталось скачать библиотеку telebot. Для этого заходим в командную строку и пишем:

pip install pytelegrambotapi



pip install pytelegrambotapi

Если всё прошло успешно, мы можем продолжать!

VPN

Думаю все знают о блокировки telegram в России и единственным решением как всегда остаётся vpn. Лично я рекомендую NordVPN.

Bot Father

В поиске telegram находим Bot Farher’a и создаем своего бота с помощью команды /newbot. Затем вводим имя и юзернейм. Обратите внимание, что юзернейм должен оканчиваться на bot!

Пишем telegram-бота на python с помощью библиотеки telebot часть 1

Как вы видите нам выдали специальный api токен, с помощью которого вы сможете управлять своим ботом (в моём случае это: 776550937:AAELEr0c3H6dM-9QnlDD-0Q0Fcd65pPyAiM). Свой токен Вы можете запомнить, но я рекомендую его записать.

Код

Настал момент, которого ждали все. Открываем PyCharm и создаем новый проект.

Тут рекомендую поставить всё как у меня (название, конечно можно изменить). После создания проекта, давайте создадим файл, в котором будет наш код. Кликните правой кнопкой по папке с вашем проектом, затем New → Python File. Отлично, начнем писать код. Импортируем библиотеку telebot, с помощью:

Теперь нужно создать переменную bot. На самом деле имя переменной может быть каким угодно, но я привык писать bot.

bot = telebot.TeleBot(‘ваш токен’)



bot = telebot.TeleBot(‘ваш токен’)

Напишем декоратор bot.message_handler(), с помощью которого наш бот будет реагировать на команду /start. Для этого в круглых скобках пишем commands=[‘start’]. В итоге у нас должно получиться это:

@bot.message_handler(commands=[‘start’])



@bot.message_handler(commands=[‘start’])

Если Вы попробуете запустить своего бота (ПКМ->Run), то у вас ничего не выйдет. Во первых в конце кода мы должны прописать bot.polling(). Это нужно для того, чтобы бот не выключился сразу, а работал и проверял, нет ли на сервере нового сообщения. А во вторых наш бот если уж и будет проверять наличие сообщений, то всё равно ничего ответить не сможет. Пора это исправлять! После нашего декоратора создаем функцию start_message, которая будет принимать параметр message (название функции может быть любым). Далее давайте реализуем отправку сообщения от самого бота. В функции пропишем bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’). Смотрите, что у Вас должно получиться:

import telebot

bot = telebot.TeleBot(‘776550937:AAELEr0c3H6dM-9QnlDD-0Q0Fcd65pPyAiM’)

@bot.message_handler(commands=[‘start’])
def start_message(message):
bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’)

bot.polling()



import telebot

 

bot = telebot.TeleBot(‘776550937:AAELEr0c3H6dM-9QnlDD-0Q0Fcd65pPyAiM’)

 

@bot.message_handler(commands=[‘start’])

def start_message(message):

    bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’)

 

bot.polling()

Проверим…

Отлично, наш бот работает! Чтобы он отвечал не только на команды, но и на сообщения, создадим новый декоратор bot.message_handler(), а в круглые скобочки напишем content_types=[‘text’]. Вообще существует множество видов контента, к примеру location, photo, audio, sticker и т.д. Но нам же нужно отвечать на текст, верно? Поэтому создаём функцию send_text, принимающую параметр message. В функции пропишем условие:

@bot.message_handler(content_types=[‘text’])
def send_text(message):
if message.text == ‘Привет’:
bot.send_message(message.chat.id, ‘Привет, мой создатель’)
elif message.text == ‘Пока’:
bot.send_message(message.chat.id, ‘Прощай, создатель’)



@bot.message_handler(content_types=[‘text’])

def send_text(message):

    if message.text == ‘Привет’:

        bot.send_message(message.chat.id, ‘Привет, мой создатель’)

    elif message.text == ‘Пока’:

        bot.send_message(message.chat.id, ‘Прощай, создатель’)

Если текст сообщения будет равен «Привет», то бот отвечает «Привет, мой создатель», а если текст сообщения будет равен «Пока», то бот ответит «Прощай, создатель». Тут думаю всё понятно. Но вы скорее всего задались вопросом, а если пользователь пропишет «привет», ну или «пРиВет», как быть в этой ситуации? Всё достаточно просто! В условии, после message.text напишите функцию .lower(), а в тексте все заглавные буквы замените на строчные. Теперь наш бот отвечает не только на «привет», но и на «ПривеТ», и даже «пРиВеТ».

Вот что у вас должно получиться:

import telebot

bot = telebot.TeleBot(‘776550937:AAELEr0c3H6dM-9QnlDD-0Q0Fcd65pPyAiM’)

@bot.message_handler(commands=[‘start’])
def start_message(message):
bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’)

@bot.message_handler(content_types=[‘text’])
def send_text(message):
if message.text.lower() == ‘привет’:
bot.send_message(message.chat.id, ‘Привет, мой создатель’)
elif message.text.lower() == ‘пока’:
bot.send_message(message.chat.id, ‘Прощай, создатель’)

bot.polling()



import telebot

 

bot = telebot.TeleBot(‘776550937:AAELEr0c3H6dM-9QnlDD-0Q0Fcd65pPyAiM’)

 

@bot.message_handler(commands=[‘start’])

def start_message(message):

    bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’)

 

@bot.message_handler(content_types=[‘text’])

def send_text(message):

    if message.text.lower() == ‘привет’:

        bot.send_message(message.chat.id, ‘Привет, мой создатель’)

    elif message.text.lower() == ‘пока’:

        bot.send_message(message.chat.id, ‘Прощай, создатель’)

 

bot.polling()

Отлично, с текстом мы разобрались, но как же отправить к примеру стикер? Всё просто! У каждого стикера есть свой id, соответственно зная id мы сможем его отправить. Получить id стикера можно двумя способами. Первый (простой) — через специального бота «What’s the sticker id?»

Ну и второй способ, для тех, кто не ищет лёгких путей. Создаем новый декоратор bot.message_handler(), вот только в скобочки пишем content_types=[‘sticker’]. Далее всё как обычно. Создаем функцию, принимающую параметр message, а вот в ней пропишем print(message). Запускаем бота.

Смотрите, как только я отправил стикер, он сразу же вывел информацию в консоль, и в самом конце будет наш id стикера (file_id). Давайте сделаем так, чтобы когда пользователь отправил боту «я тебя люблю», то бот ему ответил стикером. Создавать новый декоратор не нужно, мы просто допишем условие, которое было до этого. Вот только вместо bot.send_message() пропишем bot.send_sticker(), а вместо текста напишем id стикера.

Поздравляю, всё получилось! Думаю как отправить аудио, фото, и геолокацию, вы разберетесь сами. Я же хочу показать вам, как сделать клавиатуру, которую бот покажет вам при старте. Это уже будет сделать сложнее. Создаем переменную keyboard1, в которую запишем telebot.types.ReplyKeyboardMarkup(). Эта функция вызывает клавиатуру. Далее создадим ряды, но помните, что рядов может быть не больше 12! Для того, чтобы их создать, пишем keyboard1.row(). В круглые скобочки запишите всё что хотите, лично я напишу «Привет» и «Пока». Теперь, чтобы вызвать клавиатуру, допишем reply_markup=keyboard1 к функции отправки сообщения при старте. Вот, что у вас должно получиться:

keyboard1 = telebot.types.ReplyKeyboardMarkup()
keyboard1.row(‘Привет’, ‘Пока’)

@bot.message_handler(commands=[‘start’])
def start_message(message):
bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’, reply_markup=keyboard1)



keyboard1 = telebot.types.ReplyKeyboardMarkup()

keyboard1.row(‘Привет’, ‘Пока’)

 

@bot.message_handler(commands=[‘start’])

def start_message(message):

    bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’, reply_markup=keyboard1)

Запускаем бота…

Вы видите, что клавиатура какая-то большая. Чтобы это исправить, нужно просто в ReplyKeyboardMarkup() прописать True. Ну а если вы хотите, чтобы клавиатура скрывалась, как только пользователь нажал на нее, то напишите еще один True. Подробнее прочитать, что означают эти True вы можете в официальной документации.

keyboard1 = telebot.types.ReplyKeyboardMarkup(<span>True</span>, <span>True</span>)



keyboard1 = telebot.types.ReplyKeyboardMarkup(<span>True</span>, <span>True</span>)

Ну а на этом всё! Конечно, это не все возможно ботов в telegram, но основные возможности я вам показал. Спасибо за внимание.

Исходный код:

import telebot

bot = telebot.TeleBot(‘&lt;ваш токен&gt;’)
keyboard1 = telebot.types.ReplyKeyboardMarkup()
keyboard1.row(‘Привет’, ‘Пока’)

@bot.message_handler(commands=[‘start’])
def start_message(message):
bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’, reply_markup=keyboard1)

@bot.message_handler(content_types=[‘text’])
def send_text(message):
if message.text.lower() == ‘привет’:
bot.send_message(message.chat.id, ‘Привет, мой создатель’)
elif message.text.lower() == ‘пока’:
bot.send_message(message.chat.id, ‘Прощай, создатель’)
elif message.text.lower() == ‘я тебя люблю’:
bot.send_sticker(message.chat.id, ‘CAADAgADZgkAAnlc4gmfCor5YbYYRAI’)

@bot.message_handler(content_types=[‘sticker’])
def sticker_id(message):
print(message)

bot.polling()


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

import telebot

 

bot = telebot.TeleBot(‘&lt;ваш токен&gt;’)

keyboard1 = telebot.types.ReplyKeyboardMarkup()

keyboard1.row(‘Привет’, ‘Пока’)

 

@bot.message_handler(commands=[‘start’])

def start_message(message):

    bot.send_message(message.chat.id, ‘Привет, ты написал мне /start’, reply_markup=keyboard1)

 

@bot.message_handler(content_types=[‘text’])

def send_text(message):

    if message.text.lower() == ‘привет’:

        bot.send_message(message.chat.id, ‘Привет, мой создатель’)

    elif message.text.lower() == ‘пока’:

        bot.send_message(message.chat.id, ‘Прощай, создатель’)

    elif message.text.lower() == ‘я тебя люблю’:

        bot.send_sticker(message.chat.id, ‘CAADAgADZgkAAnlc4gmfCor5YbYYRAI’)

 

@bot.message_handler(content_types=[‘sticker’])

def sticker_id(message):

    print(message)

 

bot.polling()

Что такое message?

Наверное многие, кто писал бота по моей предыдущей статье задались вопросом, что такое message и почему к примеру, чтобы отправить сообщение мы должны указать message.chat.id в параметрах функции send_message? Для того, чтобы узнать это давайте выведем message в консоль:

@bot.message_handler(commands=[‘start’])
def start(message):
print(message)



@bot.message_handler(commands=[‘start’])

def start(message):

    print(message)

Теперь когда мы вводим команду /start, наш бот присылает огромное кол-во информации. Все, что мы сейчас получили — это ответ в формате json. Json — это простой формат для хранения структурированных данных. Все выводится в формате: ‘ключ’: значение. Давайте посмотрим на то, что получил я:

{
‘content_type’:’text’,
‘message_id’:573,
‘from_user’:{
‘id’:687595402,
‘is_bot’:False,
‘first_name’:’Dmitry’,
‘username’:’dimagorovtsov’,
‘last_name’:’Gorovtsov’,
‘language_code’:’ru’
},
‘date’:1565206363,
‘chat’:{
‘type’:’private’,
‘last_name’:’Gorovtsov’,
‘first_name’:’Dmitry’,
‘username’:’dimagorovtsov’,
‘id’:687595402,
‘title’:None,
‘all_members_are_administrators’:None,
‘photo’:None,
‘description’:None,
‘invite_link’:None,
‘pinned_message’:None,
‘sticker_set_name’:None,
‘can_set_sticker_set’:None
},
‘forward_from_chat’:None,
‘forward_from’:None,
‘forward_date’:None,
‘reply_to_message’:None,
‘edit_date’:None,
‘media_group_id’:None,
‘author_signature’:None,
‘text’:’/start’,
‘entities’:[
&lt;telebot.types.MessageEntity object at 0x03807F50&gt;
],
‘json’:{
‘message_id’:573,
‘from’:{
‘id’:687595402,
‘is_bot’:False,
‘first_name’:’Dmitry’,
‘last_name’:’Gorovtsov’,
‘username’:’dimagorovtsov’,
‘language_code’:’ru’
},
‘chat’:{
‘id’:687595402,
‘first_name’:’Dmitry’,
‘last_name’:’Gorovtsov’,
‘username’:’dimagorovtsov’,
‘type’:’private’
},
‘date’:1565206363,
‘text’:’/start’,
‘entities’:[
{
‘offset’:0,
‘length’:6,
‘type’:’bot_command’
}
]
}
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

{

    ‘content_type’:’text’,

    ‘message_id’:573,

    ‘from_user’:{

        ‘id’:687595402,

        ‘is_bot’:False,

        ‘first_name’:’Dmitry’,

        ‘username’:’dimagorovtsov’,

        ‘last_name’:’Gorovtsov’,

        ‘language_code’:’ru’

    },

    ‘date’:1565206363,

    ‘chat’:{

        ‘type’:’private’,

        ‘last_name’:’Gorovtsov’,

        ‘first_name’:’Dmitry’,

        ‘username’:’dimagorovtsov’,

        ‘id’:687595402,

        ‘title’:None,

        ‘all_members_are_administrators’:None,

        ‘photo’:None,

        ‘description’:None,

        ‘invite_link’:None,

        ‘pinned_message’:None,

        ‘sticker_set_name’:None,

        ‘can_set_sticker_set’:None

    },

    ‘forward_from_chat’:None,

    ‘forward_from’:None,

    ‘forward_date’:None,

    ‘reply_to_message’:None,

    ‘edit_date’:None,

    ‘media_group_id’:None,

    ‘author_signature’:None,

    ‘text’:’/start’,

    ‘entities’:[

        &lt;telebot.types.MessageEntity object at 0x03807F50&gt;

    ],

    ‘json’:{

        ‘message_id’:573,

        ‘from’:{

            ‘id’:687595402,

            ‘is_bot’:False,

            ‘first_name’:’Dmitry’,

            ‘last_name’:’Gorovtsov’,

            ‘username’:’dimagorovtsov’,

            ‘language_code’:’ru’

        },

        ‘chat’:{

            ‘id’:687595402,

            ‘first_name’:’Dmitry’,

            ‘last_name’:’Gorovtsov’,

            ‘username’:’dimagorovtsov’,

            ‘type’:’private’

        },

        ‘date’:1565206363,

        ‘text’:’/start’,

        ‘entities’:[

            {

                ‘offset’:0,

                ‘length’:6,

                ‘type’:’bot_command’

            }

        ]

    }

}

К примеру из всей этой информации мы хотим получить id чата, из которого я отправлял сообщение. Для этого обратимся к ключу chat.

Запрос:

Ответ:

{‘type’: ‘private’, ‘last_name’: ‘Gorovtsov’, ‘first_name’: ‘Dmitry’, ‘username’: ‘dimagorovtsov’, ‘id’: <span>687595402</span>, ‘title’: None, ‘all_members_are_administrators’: None, ‘photo’: None, ‘description’: None, ‘invite_link’: None, ‘pinned_message’: None, ‘sticker_set_name’: None, ‘can_set_sticker_set’: None}



{‘type’: ‘private’, ‘last_name’: ‘Gorovtsov’, ‘first_name’: ‘Dmitry’, ‘username’: ‘dimagorovtsov’, ‘id’: <span>687595402</span>, ‘title’: None, ‘all_members_are_administrators’: None, ‘photo’: None, ‘description’: None, ‘invite_link’: None, ‘pinned_message’: None, ‘sticker_set_name’: None, ‘can_set_sticker_set’: None}

Смотрите, у ключа chat есть еще несколько ключей: first_name, last_name, username… и у каждого из них есть свои значения. Теперь обратимся к ключу id:

Как вы видите для того чтобы получить нужное значение необходимо просто записать название ключей через точку. А теперь смотрим на ответ от сервера:

<span>687595402</span>



<span>687595402</span>

Все идет как надо! Мы получили id чата, собственно как и хотели! А теперь получим имя отправителя. Тут, как вы заметили нужно использовать ключ from_user.

Запрос:

Ответ:

{‘id’: <span>687595402</span>, ‘is_bot’: False, ‘first_name’: ‘Dmitry’, ‘username’: ‘dimagorovtsov’, ‘last_name’: ‘Gorovtsov’, ‘language_code’: ‘ru’}



{‘id’: <span>687595402</span>, ‘is_bot’: False, ‘first_name’: ‘Dmitry’, ‘username’: ‘dimagorovtsov’, ‘last_name’: ‘Gorovtsov’, ‘language_code’: ‘ru’}

Теперь достанем значение у ключа first_name:

print(message.from_user.first_name)



print(message.from_user.first_name)

Ну вот и все! За пару секунд мы смогли получить id чата и мое имя в telegram. И еще раз, для тех кто не понял:

Чтобы получить значение ключа first_name, нам нужно сначала обратиться к ключу chat, а только потом уже к first_name!

Теперь смотрите, для того, чтобы отправить сообщение в какой-либо чат нам необходимо указать несколько параметров в функцию send_message. Первый параметр — это chat_id, собственно сам id чата. Второй — text, текст сообщения. И как вы догадались, вместо того, чтобы писать message.chat.id, мы можем написать свои данные! Вот так можно прислать сообщение самому себе, если указать в параметрах свой id:

bot.send_message(&lt;ваш id&gt;, <span>’Текст сообщения'</span>)



bot.send_message(&lt;ваш id&gt;, <span>’Текст сообщения'</span>)

Ну а когда мы пишем message.chat.id, мы подразумеваем, что бот отправит сообщение в чат, из которого его вызвали.

Заключение

Ну а на этом всё! Надеюсь вы поняли как получать данные от сервера, обрабатывать их и использовать где нужно. Спасибо за внимание.

источник

 

Как создать чат-бота с нуля на Python: подробная инструкция

Аналитики Gartner утверждают, что к 2020 году 85% взаимодействий клиентов с сервисами сведется к общению с чат-ботами. В 2018 году они уже обрабатывают около 30% операций. В этой статье мы расскажем, как создать своего чат-бота на Python.

Возможно, вы слышали о Duolingo : популярное приложение для изучения иностранных языков, в котором обучение проходит в форме игры.Duolingo популярен благодаря инновационному стилю обучения. Концепция проста: от пяти до десяти минут интерактивного обучения в день достаточно, чтобы выучить язык.

Несмотря на то что Duolingo позволяет изучить новый язык, у пользователей сервиса возникла проблема. Они почувствовали, что не развивают разговорные навыки, так как обучаются самостоятельно. Пользователи неохотно обучались в парах из-за смущения. Эта проблема не осталась незамеченной для разработчиков.

Команда сервиса решила проблему, создавая чат-бота в приложении, чтобы помочь пользователям получать разговорные навыки и применять их на практике.

Формула «

» использует «собеседника» из набора, пока не будет смущение в достаточной степени, чтобы перейти к общению с другими пользователями. Это решило проблему пользователей и ускорило обучение через приложение.

Итак, что такое чат-бот?

Чат-бот — это программа, которая снабжает потребности людей, а помогает удовлетворить их (денежная транзакция, бронирование отелей, составление документов).Сегодня почти каждая компания имеет чат-бота для взаимодействия с пользователями. Некоторые способы использования чат-ботов:

  • предоставление информации о рейсе;
  • пользователям предоставление доступа к информации об их финансах;
  • служба поддержки.

Возможности безграничны.

История чат-ботов восходит к 1966 году, когда Джозеф Вейценбаум разработал компьютерную программу ELIZA. Программа подражает манере речи психотерапевта и состоит лишь из 200 строк кода.Пообщаться с Элизой можно до сих пор на сайте.

Как работает чат-бот?

Существует два типа ботов: работающие по правилам и самообучающиеся.

  • Бот первого типа отвечает на вопросы, использует на некоторых правилах , которому он обучен. Правила могут быть как простыми, так и очень сложными. Боты могут обрабатывать простые запросы, но не справлятся со сложными.
  • Самообучающиеся боты примеры использования основанных на машинном обучении методов и определенно более эффективны, чем боты первого типа.Самообучающиеся боты бывают двух типов: поисковые и генеративные .

В поисковых ботах используются эвристические методы для выбора из библиотеки предопределенных реплик. Такие чат-боты используют текст сообщения и контекст диалога для выбора из предопределенного списка. Включает в себя текущее положение в древе диалога, все предыдущие сообщения и сохраненные ранее переменные (например, имя пользователя). Эвристика для выбора может быть спроектирована по-разному: от условной логики «или-или» до машинных классификаторов.

Генеративные боты могут самостоятельно создавать ответы и не всегда используются одним из предопределенных вариантов. Это делает их интеллектуальными, так как такие боты изучают каждое слово в запросе и генерируют ответ.

В этой статье мы научимся писать код простых чат-ботов на основе библиотеки NLTK.

Создание бота на Python

Предполагается, что вы умеете пользоваться библиотеками scikit и NLTK .Однако, если вы новичок в обработке естественного языка (НЛП), вы все равно можете прочитать статью, а затем изучить соответствующую литературу.

Обработка естественного языка (NLP)

Обработка естественного языка — это область исследований, в которой изучается взаимодействие между человеческим языком и компьютером. NLP основана на синтезе компьютерных наук, искусственного интеллекта и вычислительной лингвистики. НЛП — это способ для компьютеров анализировать, понимать и извлекать из человеческого языка разумным и полезным образом.

Краткое введение в NLKT

NLTK (Natural Language Toolkit) — платформа для создания программ на Python для работы с естественной речью. NLKT предоставляет простые в использовании интерфейсы для более чем 50 корпораций и лингвистических ресурсов, таких как WordNet, а также набор библиотек для обработки текста в целях классификации, токенизации, генерации, тегирования, синтаксического анализа и понимания семантики, создания оболочки библиотек NLP для коммерческого применения.

Книга Обработка естественного языка с помощью Python — практическое введение в программирование для обработки языка. Рекомендуем ее прочитать, если вы владеете английским языком.

Загрузка и установка НЛТК

  • Установите NLTK: запустите pip install nltk.
  • Тестовая установка: запустите python , затем введите import nltk.

Инструкции для конкретных платформ смотрите здесь.

Установка пакетов NLTK

Импортируйте NLTK и запустите nltk.скачать () . Это откроет загрузчик NLTK, где вы сможете выбрать версию кода и модели для загрузки. Вы также можете загрузить все пакеты сразу.

Предварительная обработка текста с помощью НЛТК

Основная проблема с данными заключается в том, что они представлены в текстовом формате. Для решения задач алгоритмов машинного обучения требуется некий вектор свойств. Поэтому прежде чем создать проект по НЛП. Предварительная обработка текста включает в себя:

  • Преобразование букв в заглавные или строчные , чтобы алгоритм не обрабатывал одни и те же слова повторно.
  • Токенизация . Токенизация — инструмент, используемый для описания процесса преобразования обычных текстовых строк в список токенов, то есть слов. Токенизатор предложений используется для составления списка предложений. Токенизатор слов составляет список слов.

Пакет NLTK включает в себя приведенный токенизатор Punkt для английского языка.

  • Удаление шума , то есть всего, что не является цифрой или буквой;
  • Удаление стоп-слов .Иногда из словаря полностью исключаются некоторые распространенные слова, которые, как считается, имеют большие значения для формирования ответа на вопрос пользователя. Эти слова называются стоп-словами (междометия, артикли, вводные слова) ;
  • Cтемминг : приведение слова к коренному значению. Например, если нам нужно провести стемминг слов «стемы», «стемминг», «стемированный» и «стемизация», результатом будет одно слово — «стем».
  • Лемматизация .Лемматизация — немного отличающийся от стемминга метод. Основное существующее между ними заключается в том, что стемминг создает несуществующие слова. Таким образом, ваш исходный стем, то есть слово, которое получается после стемминга, не всегда можно найти в этом, а лемму — можно. Пример лемматизации: «бег» — основа для слов «бег» или «бег», «лучше» и «хорошо» находятся в одной и той же лемме и потому считаются одинаковыми.

Набор слов

После первого этапа предварительной обработки нужно преобразовать текст в вектор (или массив) чисел.«Набор слов» — это представление текста, описывающего наличие слов в тексте. «Набор слов» состоит из:

  • словаря известных слов;
  • частот, с постоянно встречается слово в тексте.

Почему используется слово «набор»? Это связано с тем, что информация о порядке или структуре слов в тексте отбрасывается, и модель учитывает только то, как часто слова встречаются в тексте, но не то, где именно они находятся.

Идея «набора слов» в том, что тексты похожи по содержанию, если включают в себя похожие слова. Кроме того, кое-что узнать о содержании текста можно лишь по набору слов.

Например, если словарь содержит слова {Learning, is, the, not, great} и мы хотим составить вектор предложения «Обучение — это здорово», получится вектор (1, 1, 0, 0, 1).

Метод TF-IDF

Проблема «набора слов» заключается в том, что в тексте доминируют часто встречающиеся слова, которые не содержат ценную для нас информацию.Также «набор слов» присваивает большой длинный текстам по сравнению с короткими.

Один из подходов к решению этих проблем в том, чтобы вычислить частоту появления слова не в одном тексте, а во всех сразу. За счет этого вкладка, например, артиклей «a» и «the» будет нивелирован. Такой подход называется TF-IDF (Term Frequency-Inverse Document Frequency) и состоит из двух этапов:

  • TF — вычисление частоты появления слова в одном тексте
 TF = (Число раз, когда слово "t" встречается в тексте) / (Количество слов в тексте) 
  • IDF — вычисление того, на сколько редко встречается слово во всех текстах
 IDF = 1 + log (N / n), где N - общее количество текстов, n - во скольких текстах встречается "t" 

Коэффициент TF-IDF — это вес, часто используется для обработки информации и интеллектуального анализа текста.Он является статистической мерой, используемой для оценки важности слова для некоторого наборе текстов.

Пример

Рассмотрим текст, 100 слов, в котором слово «телефон» появляется 5 раз. Параметр TF для слова «телефон» равенство (5/100) = 0,05.

Теперь предположим, что у нас 10 миллионов документов, и слово появляется в тысяче из них. Коэффициент вычисляется как 1 + log (10 000 000/1000) = 4. Таким образом, TD-IDF равенство 0,05 * 4 = 0,20.

TF-IDF может быть реализован в scikit так:

 из sklearn.feature_extraction.text import TfidfVectorizer 

Коэффициент Отиаи

TF-IDF — это преобразование, применяемое к текстам для использования двух вещественных векторов в векторном пространстве. Тогда мы можем получить коэффициент Отиаи любой пары векторов, вычислив их поэлементное произведение и разделив его на произведение их норм. Таким образом, получается косинус угла между векторами.Коэффициент Отиаи является мерой сходства между двумя ненулевыми явлениями. Используя эту формулу, можно вычислить схожесть между любыми текстами d1 и d2.

 Косинусное подобие (d1, d2) = Точечное произведение (d1, d2) / || d1 || * || d2 || 

Здесь d1, d2 — два ненулевых события.

Подробное объяснение и практический пример TF-IDF и Коэффициенты приведенных в посте по ссылке.

Пришло время перейти к решению нашей задачи, то есть создание-бота.Назовем его «ROBO».

 

Обучение чат-бота

В нашем примере мы будем использовать страницу Википедии в качестве текста. Скопируйте содержимое страницы и поместите его в текстовый файл под названием «chatbot.txt». Можете сразу использовать другой текст.

Импорт необходимых библиотек

 импорт НЛТК
импортировать numpy как np
случайный импорт
импортировать строку # для обработки стандартных строк Python 

Чтение данных

Выполним чтение файла corpus.txt и преобразуем весь текст в предложениях и список слов для дальнейшей предварительной обработки.

 f = open ('chatbot.txt', 'r', errors = 'ignore') 
 raw = f.read () 
 raw = raw.lower () # преобразует в нижний регистр 
 nltk.download ('punkt') # только при первом использовании
nltk.download ('wordnet') # только при первом использовании 
 sent_tokens = nltk.sent_tokenize (raw) # преобразуется в список предложений
word_tokens = nltk.word_tokenize (raw) # преобразует в список слов 

Давайте рассмотрим пример файлов sent_tokens и word_tokens

  sent_tokens [: 2] 
['чат-бот (также известный как чат-бот, чат-бот, бот, им-бот, интерактивный агент или искусственный объект разговора) - это компьютерная программа или искусственный интеллект, который ведет разговор с помощью слуховых или текстовых методов.',
 «такие программы часто разрабатываются, чтобы убедительно моделировать поведение человека в качестве собеседника, тем самым проходя тест Тьюринга».] 
  word_tokens [: 2] 
['a', 'chatbot', '(', 'также', 'известный'] 

Предварительная обработка исходного текста

Теперь определим функцию LemTokens, которая примет в качестве входных параметров токены и выдастмированные токены.

 леммер = nltk.stem.WordNetLemmatizer ()
#  WordNet - семантически ориентированный словарь английского языка, входящий в состав NLTK. 
 def LemTokens (жетоны):
    return [lemmer.lemmatize (токен) для токена в токенах]
remove_punct_dict = dict ((ord (punct), None) для знака в строке. пунктуация)
def LemNormalize (текст):
    вернуть LemTokens (nltk.word_tokenize (text.lower (). translate (remove_punct_dict))) 

Подбор ключевых слов

Определим реплику-приветствие бота. Если пользователь приветствует бота, бот поздоровается в ответ. В ELIZA используется простое сопоставление ключевых слов для приветствий.Будем использовать ту же идею.

 GREETING_INPUTS = («привет», «привет», «привет», «привет», «как дела», «привет»,) 
 GREETING_RESPONSES = [«привет», «привет», «* кивает *», «привет», «привет», «я рад! Ты говоришь со мной»] 
 def приветствие (предложение):
 
    на слово в строке предложение.split ():
        если word.lower () в GREETING_INPUTS:
            вернуть random.choice (GREETING_RESPONSES) 

Генерация ответа

Чтобы сгенерировать ответ нашего бота для ввода вопросов, будет концепция схожести текстов.Поэтому мы начинаем с импорта необходимых модулей.

 из sklearn.metrics.pairwise import cosine_similarity 

Этот модуль будет Предложить поиск в запросе пользователя ключевых слов. Это самый простой способ создать чат-бота.

Определим функцию отклика , которая возвращает один из возможных ответов. Если запрос не соответствует ни одному ключевому слову, бот выдает ответ «Извините! Я вас не понимаю ».

Ответ

 def (user_response):
    robo_response = '
 TfidfVec = TfidfVectorizer (tokenizer = LemNormalize, stop_words = 'english')
    tfidf = TfidfVec.fit_transform (отправленные токены)
    vals = cosine_similarity (tfidf [-1], tfidf)
    idx = vals.argsort () [0] [- 2]
    квартира = vals.flatten ()
    flat.sort ()
    req_tfidf = квартира [-2] 
, если (req_tfidf == 0):
        robo_response = robo_response + «Мне очень жаль! Я вас не понимаю»
        вернуть robo_response
    еще:
        robo_response = robo_response + sent_tokens [idx]
        вернуть robo_response 

Наконец, мы задаем реплики бота в начале и конце переписки, в зависимости от реплик пользователя.

 flag = True
print ("ROBO: Меня зовут Робо. Я отвечу на ваши вопросы о чат-ботах. Если вы хотите выйти, введите Bye!") 
 в то время как (flag == True):
    user_response = input ()
    user_response = user_response.lower ()
    если (user_response! = 'пока'):
        if (user_response == 'спасибо' или user_response == 'спасибо'):
            flag = False
            print ("ROBO: Добро пожаловать ..")
        еще:
            если (приветствие (user_response)! = Нет):
                print ("ROBO:" + приветствие (user_response))
            еще:
                sent_tokens.добавить (user_response)
                word_tokens = word_tokens + nltk.word_tokenize (user_response)
                final_words = список (набор (word_tokens))
                print ("ROBO:", end = "")
                печать (ответ (user_response))
                sent_tokens.remove (user_response)
    еще:
        flag = False
        print ("ROBO: Пока! береги себя ..") 

Вот и все. Мы написали код нашего первого бота в NLTK. Здесь вы можете найти весь код вместе с текстом.Теперь давайте посмотрим, как он взаимодействует с людьми:

Получилось не так уж плохо. Даже если чат-бот не смог дать удовлетворительного ответа на некоторые вопросы, он хорошо справился с другими.

Заключение

Хотя наш примитивный бот ли обладает когнитивными навыками, это был неплохой способ разобраться с НЛП и узнать о работе чат-ботов. «ROBO», по крайней мере, отвечает на запросы пользователя. Он, конечно, не обманет ваших друзей, и для коммерческой системы вы захотите рассмотреть одну из наших бот-платформ или фреймворки, но этот пример поможет вам продумать программууру бота.


Интересные статьи:

.

Создание Discord-бота на Python. Часть 1 / Хабр

Версии, которые стоят у автора

Версия Python: 3.8.2
Версия discord.py: 1.3.3

Приветствую, хабровчане и другие пользователи интернета. Сегодня я начну цикл статей, посвященное созданию Discord-бота с помощью библиотеки discord.py. Мы рассмотрим создание как и примитивного бота, как и «продвинутого» бота с модулями.В этой статье мы сделаем стандартную команду и ещё одну небольшую команду. Начнём!

Создание бота и получение токена

Для того, чтобы добавить бота на сервер, нужно создать свое приложение и во вкладку Общая информация скопировать идентификатор клиента.

Здесь заменяем CLID на ранее скопированный Client ID.

  https://discordapp.com/oauth3/authorize?&client_id=CLID&scope=bot&permissions=8  

Во вкладке Бот создаём бота и копируем токен.

Написание кода

Устанавливаем саму библиотеку.

  pip install discord  

Создаём файл config.py (так удобнее), и создаём там словарь.

  settings = {
    'token': 'Ваш токен',
    'bot': 'Имя бота',
    'id': идентификатор клиента бота, без кавычек,
    'префикс': 'Префикс бота'
}  

Создаём main-файл, название может быть любым.
Импортируем библиотеку и наш файл конфигурации:

  import discord
от разлада.команды импорта ext
из настроек импорта конфигурации  

Создаём «тело» бота, название может быть любым:

  bot = commands.Bot (command_prefix = settings ['prefix']) # Так как мы указали префикс в settings, обращаемся к словарю с ключом префикс.  

Начинаем писать основной код.

  @ bot.command () # Не передаём аргумент pass_context, так как он был нужен в старых версиях.
async def hello (ctx): # Создаём функцию и передаём аргумент ctx.
    автор = ctx.message.author # Объявляем переменную автора и записываем туда информацию об авторе.

    await ctx.send (f'Hello, {author.mention}! ') # Выводим сообщение с упоминанием автора, обращаясь к альтернативному автору.  

В конце запускаем бота с помощью:

  bot.run (settings ['token']) # Обращаемся к словарю settings с ключом токена, для получения токена  

Полный код

  импортный рознь
от разлада.команды импорта ext
из настроек импорта конфигурации

bot = commands.Bot (command_prefix = настройки ['префикс'])

@ bot.command () # Не передаём аргумент pass_context, так как он был нужен в старых версиях.
async def hello (ctx): # Создаём функцию и передаём аргумент ctx.
    author = ctx.message.author # Объявляем переменную автора и записываем туда информацию об авторе.
    await ctx.send (f'Hello, {author.mention}! ') # Выводим сообщение с упоминанием автора, обращаясь к альтернативному автору.

bot.run (settings ['token']) # Обращаемся к словарю settings с ключом токена, для получения токена  

Должно получится так:

Бонусный туториал!

Сделаем вывод случайных картинок с лисами
Для этого импортируем еще пару библиотек:

  import json
запросы на импорт  

Приступим к написанию команды.

  @ bot.command ()
async def fox (ctx):
    response = requests.get ('https://some-random-api.ml/img/fox') # Get-запрос
    json_data = json.loads (response.text) # Извлекаем JSON

    embed = discord.Embed (color = 0xff9900, title = 'Random Fox') # Создание Embed'а
    embed.set_image (url = json_data ['link']) # Устанавливаем картинку Embed'a
    await ctx.send (embed = embed) # Отправляем Embed  

Должно получится так:

Конец

На этом 1 часть закончена.Скоро будет опубликована 2 часть.

.

Создание простого чат-бота в VK на Python 3 / Хабр

Создание основы для работы бота будет состоять из следующих этапов:

  1. Создание бота в ВК
  2. Генерирование API- ключ
  3. Создание программы бота через LongPoolVK

Для кого эта статья?

Статья рассчитана для начинающих программистов. Метод работы программы очень прост и любой, кто умеет разбираться в синтаксисе Питона и немного знающий ООП сможет его реализовать для своих нужд.В принципе даже не зные никаких принципов ООП, думаю можно научиться использовать простые функции или хотя бы в крайнем случае использовать готовые исходники из GitHub.

Что есть в этой статье?

Создание основы бота. После этого его можно будет запрограммировать как-угодно. Автоматизировать какую-то рутину или использовать как собеседник.

Улучшенная (слегка усложненная версия бота). Я решил сначала ввести простой процедурный код бота, затем слегка усложнить его, дополнительные функции, значительно улучшающие работу бота.

Добавление функции передачи погоды. Научим бота говорить нам погоду.

Создание бота в ВК

Начнем мы с создания бота, а именно группа в ВК.

Для этого нужно зайти в «группы» → «создать сообщество».

Выберите любой тип сообщества и введите название, тематику группы.

На открывшейся странице настроек, выберите «Работа с API»

Далее, необходимо создать API-ключ.

Укажите нужные параметры доступа для вашего API-ключа.

Скорее всего, вам придётся подтверждать действие в ВК с помощью мобильного телефона. Затем скопируйте полученный API-ключ где-нибудь в файл. Он нам еще понадобится.

Затем нужно разрешить сообщения. Для этого переходим в «сообщения» и включаем их.

Приступим к программной части бота

Мы не будем реализовывать его через запросы к ВК, а если быть точнее, просто используем библиотеку VkLongPool, которая сделает это за нас.

Для этой необходимой библиотеки vk_api.Установим его через pip:

python -m pip install vk_api

Но лично я работаю с виртуальным окружением Анаконда. С этим часто работают проблемы при первой работе. Обычно проблема в том, что система не распознают команду «python». А решается эта проблема путем добавления его в PATH.

Приступим к самому коду:

Импортируем нужные модули:

  импорт vk_api
from vk_api.longpoll import VkLongPoll, VkEventType  

Затем код:

  def write_msg (user_id, message):
    vk.метод ('messages.send', {'user_id': user_id, 'message': message})

# API-ключ созданный ранее
token = "6a9c267cd469388709a9e9acaddbe0aa81a0abbf12239b3e597a31729ffbddb9c88e80a443554c918b8f7"

# Авторизуемся как сообщество
vk = vk_api.VkApi (токен = токен)

# Работа с сообщениями
longpoll = VkLongPoll (vk)

# Основной цикл
для события в longpoll.listen ():

    # Если пришло новое сообщение
    если event.type == VkEventType.MESSAGE_NEW:
    
        # Если оно имеет метку для меня (то есть бота)
        если событие.мне:
        
            # Сообщение от пользователя
            request = event.text
            
            # Каменная логика
            если запрос == "привет":
                write_msg (event.user_id, "Хай")
            elif request == "пока":
                write_msg (event.user_id, "Пока ((")
            еще:
                write_msg (event.user_id, «Не поняла вашего ответа ...»)  

Функция write_msg получает id пользователя ВК, которому оно отправит сообщение и собственно само сообщение.

  def write_msg (идентификатор_пользователя, сообщение):
    vk.method ('messages.send', {'user_id': user_id, 'message': message})  

Авторизовавшись как сообщество и настроив longpool:

  # API-ключ созданный ранее
token = "6a9c267cd469388709a9e9acaddbe0aa81a0abbf12239b3e597a31729ffbddb9c88e80a443554c918b8f7"

# Авторизуемся как сообщество
vk = vk_api.VkApi (токен = токен)

# Работа с сообщениями
longpoll = VkLongPoll (vk)
Войдем в основной цикл:

# Основной цикл
для события в лонгполле.слушайте ():  

В нем мы циклически будем проверять на наличие событий-ов. А получить тип события-а сможем с помощью event.type.

После этого сообщения от пользователя сможем отправить ему соответствующее письмо с помощью уже созданной функции write_msg.

Итак, мы создали очень простую бота в ВК с такой же простой реализацией. А логику бота можно программировать как душе угодно.

Листинг кода в GH

Теперь приступим к более реальному программированию

Создадим класс VkBot в файле vk_bot.py, который будет служить нам ботом.

  класс VkBot:

    def __init __ (self, user_id):
    
        print ("Создан объект бота!")
        self._USER_ID = user_id
        self._USERNAME = self._get_user_name_from_vk_id (user_id)
        
        self._COMMANDS = ["ПРИВЕТ", "ПОГОДА", "ВРЕМЯ", "ПОКА"]  

И добавим туда метод с помощью которого можно получить имя пользователя через vk id.

  def _get_user_name_from_vk_id (self, user_id):
    request = requests.get ("https: // vk.com / id "+ str (user_id))
    bs = bs4.BeautifulSoup (request.text, "html.parser")
    
    user_name = self._clean_all_tag_from_str (bs.findAll ("название") [0])
    
    return user_name.split () [0]  

Это делается с помощью beatifulsoup4.

Устанавливаем если его нет:

python -m pip install bs4

На него есть достаточное количество статей, которые стоит изучить. С помощью него же создадим еще несколько методов:

  # Получение времени:
def _get_time (сам):
    запрос = запросы.получить ("https://my-calend.ru/date-and-time-today")
    b = bs4.BeautifulSoup (request.text, "html.parser")
    return self._clean_all_tag_from_str (str (b.select (". page") [0] .findAll ("h3") [1])). split () [1]

# Получение погоды
def _get_weather (city: str = "санкт-петербург") -> список:
    request = requests.get ("https://sinoptik.com.ru/погода-" + город)
    b = bs4.BeautifulSoup (request.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 ()
    результат = ''
    результат = результат + ('Утром:' + weather1 + '' + weather2) + '\ n'
    результат = результат + ('Днём:' + weather3 + '' + weather4) + '\ n'
    temp = b.select ('. rSide .description')
    weather = temp [0] .getText ()
    результат = результат + weather.strip ()
    
    вернуть результат
    
 # Метод очистки от ненужных тэгов
 
@staticmethod
def _clean_all_tag_from_str (строка_строка):
    "" "
    Очистка строки stringLine от тэгов и их содержимых
    : param string_line: Очищаемая строка
    : return: очищенная строка
    "" "
    результат = ""
    not_skip = Верно
    для i в списке (string_line):
        если not_skip:
            если я == "<":
                not_skip = Ложь
            еще:
                результат + = я
        еще:
            если я == ">":
                not_skip = Верно
    
    вернуть результат  

Измените параметр _get_weather на нужный город, после этого метод можно будет вызвать с указанием города, по умолчанию будет ваше указанное значение.

С помощью этих методов мы сможем получить время и погоду. Эти методы вырезаны из моего основного проекта бота. Следует организовать их в отдельных пакетах и ​​классах, применяя наследование. Но ради пример работы, я решил вместить все это в один класс бота, что конечно плохо.

Создадим основной метод new_message, который будет обрабатывать сообщение пользователя и возвращать ответ:

  def new_message (self, message):

    # Привет
    если message.upper () == self._COMMANDS [0]:
        return f "Привет-привет, {сам._USERNAME}! "
    
    # Погода
    elif message.upper () == self._COMMANDS [1]:
        вернуть self._get_weather ()
    
    # Время
    elif message.upper () == self._COMMANDS [2]:
        вернуть self._get_time ()
    
    # Пока
    elif message.upper () == self._COMMANDS [3]:
        return f "Пока-пока, {self._USERNAME}!"
    
    еще:
        return "Не понимаю о чем вы ..."  

Теперь вернемся к запускаемому файлу:

Импортируем класс нашего бота:

  из vk_bot import VkBot  

Изменим основной наш цикл:

  печать («Сервер запущен»)
для события в лонгполле.Слушать():
    если event.type == VkEventType.MESSAGE_NEW:
        если event.to_me:
        
            print ('Новое сообщение:')
            print (f'Для меня by: {event.user_id} ', end =' ')
            
            bot = VkBot (event.user_id)
            write_msg (event.user_id, bot.new_message (event.text))
            
            print ('Текст:', event.text)  

То есть теперь мы будем отправлять полученное сообщение объекту бота, который вернет нам нужный ответ.

Это усложнение программы необходимо просто, если вы хотите улучшить функционал бота:

Создайте пакеты и классы для каждой функции _get_time и _get_weather.Организуйте наследование с общего класса. И каждую новую функцию распределите в отдельных классах, лучше всего, конечно, еще и разделить на пакеты.

Добавьте словарь с ключом координатора пользователя и величиной объекта бота. Таким образом, не придется каждый раз в цикле создать объект бота. К тому же, это обеспечит пользование пользователями сразу в сложных конструкциях.

Таким образом, выбрав хорошую электрическую энергию кода, вы сможете создать многофункционального бота.

К примеру, я научил своего бота проигрывать музыку на компьютере, открывать рейтинг с телефона. Присылать рецепты блюд на завтрак, обед, ужин.

Вы же можете редактировать бота под себя.

Бот из статьи

Основной проект бота (улучшенный) на GH

Буду рад вашим идеям. По любым вопросам пишите.

.

Как создать бота Telegram с использованием Python

14 февраля 2017 г., Python,
134421 Представления

За последний год Telegram представил множество новых функций, включая игры внутри приложений, ботов, телеграф и мгновенные просмотры, каналы, группы и многое другое. Что будет следующей потрясающей функцией? Никто не знает. В этой скромной заметке я хотел бы показать вам, как можно создать простого бота для телеграмм, используя популярный язык программирования Python.

Боты хороши во многих вещах, особенно в автоматизации скучных задач. Вам решать, какие функции будет у вашего будущего бота, но сегодня мы собираемся создать тот, который будет взаимодействовать с Planet Python, популярным агрегатором новостей Python. Бот просто проанализирует последний контент и отправит его вам через Telegram.

Наше приложение будет состоять из приложения django, и его исходный код доступен на моем github как репозиторий planetpython_telegrambot. Не стесняйтесь форкнуть и делать все, что хотите 🙂

Создание бота Telegram

Прежде всего, чтобы создать бота Telegram, у вас должна быть учетная запись Telegram.Если да, то откройте свое приложение Telegram (мобильное или настольное) и выполните следующие действия:

  • Добавить в список контактов BotFather
  • Начните разговор с BotFather , нажав кнопку Начать . Вы сразу увидите список команд.
  • Чтобы создать нового бота для телеграмм, вы должны ввести команду / newbot и следовать инструкциям. Будьте осторожны, имя пользователя вашего бота должно заканчиваться на bot .Например, DjangoBot или Django_bot.
  • Я решил выбрать PlanetPythonBot , что довольно просто с учетом его функциональности.

Если все в порядке, в конце вы увидите токен бота или ключ доступа к API.

Кстати, BotFather также может выполнять за вас следующие действия:

  • Положите описание своему боту
  • Загрузить аватар
  • Изменить токен доступа
  • Удалите своего бота и т. Д.

Давайте закодируем бота Telegram

Ранее я упоминал, что мы собираемся создать приложение Django. Но это не обязательно, вы также можете написать простейший скрипт Python, который будет периодически связываться со службой Telegram, используя вызов API getUpdates. Telegram имеет два взаимоисключающих подхода к обмену данными через API:

  • с использованием вызова API getUpdates
  • настройка Webhook

Идея Webhook состоит в том, чтобы предоставить вашему боту специальный URL-адрес (пост-бэк), и когда происходит событие (например, кто-то начинает разговор с ботом), служба Telegram отправляет почтовые запросы на этот URL-адрес, предоставляя необходимую информацию (идентификатор чата, имя пользователя , содержание и дополнительная метаинформация).Мы собираемся использовать этот подход при создании собственного веб-приложения. Чтобы установить обратный URL, мы будем использовать вызов API setWebhook . Но Telegram требует HTTPS, здесь у вас есть два варианта:

  • Получите действующий сертификат SSL (купите или установите бесплатно в Let’s Encrypt)
  • Создать самоподписанный сертификат с помощью таких инструментов, как OpenSSL

Более подробная информация о getUpdates и setWebhook доступна здесь и здесь.

Для связи с Telegram API мы собираемся использовать библиотеку Python под названием telepot. Давайте напишем код на Python, но перед этим я рекомендую вам настроить отдельную среду Python, используя такие инструменты, как virtualenv:

.

  pip install telepot  

Следующий код показывает простейший способ связи с Telegram API (например, запуск оболочки Python). Вы должны заменить значение переменной токена токеном доступа вашего бота.

  импортный телепот
токен = '123456'
TelegramBot = телепот.Бот (токен)
распечатать TelegramBot.getMe ()
  

После выполнения вышеуказанного кода вы получите что-то вроде этого:

  {u'username ': u'PythonPlanetBot', u'first_name ': u'Python Planet Bot', u'id ': 199266571}  

Поздравляем! Вы сделали свой первый вызов API getMe в Telegram, который возвращает информацию о боте, такую ​​как его имя пользователя, идентификатор бота и т. Д.

Теперь добавьте своего вновь созданного бота в список контактов Telegram и начните разговор, отправив / start .

А теперь выполните следующий код:

  TelegramBot.getUpdates ()  

И получим:

  [{u'message ': {u'date': 1459927254, u'text ': u' / start ', u'from': {u'username ': u'adilkhash', u'first_name ': u 'Адиль', u'id ': 31337}, u'message_id': 1, u'chat ': {u'username': u'adilkhash ', u'first_name': u'Adil ', u'type': u'private ', u'id': 7350}}, u'update_id ': 649179764}]
  

getUpdates Вызов API возвращает список объектов с именем Update.Каждый объект обновления состоит из объектов сообщения. В нашем примере с ботом нас интересует только сообщение, которое имеет текстовый атрибут (контент) и объект чата, который указывает пользователя, который начал разговор, и идентификатор чата, на который нужно ответить. Также обратите внимание на атрибут update_id , его значение важно, если вы собираетесь использовать подход getUpdates для мониторинга входящих запросов вместо Webhooks . При вызове метода getUpdates вы можете указать смещение, обычно значение смещения рассчитывается как значение update_id последнего вызова + 1, что означает, что вы получите все, кроме того, что вы уже получили от последнего вызова 🙂 Звучит беспорядочно, позвольте мне проиллюстрировать кодом.Отправьте сообщение своему боту еще раз и позвоните:

  TelegramBot.getUpdates (649179764 + 1)  
  [{u'message ': {u'date': 1459928527, u'text ': u'hello bro', u'from ': {u'username': u'adilkhash ', u'first_name': u 'Адиль', u'id ': 31337}, u'message_id': 13, u'chat ': {u'username': u'adilkhash ', u'first_name': u'Adil ', u'type': u'private ', u'id': 7350}}, u'update_id ': 649179765}]  

Достаточно знать, чтобы создать нашего Telegram-бота.Посмотрим, как будет выглядеть приложение django.

Сначала мы должны проанализировать RSS-канал Planet Python. Это делает следующая функция:

  # - * - кодировка: utf8 - * -
from xml.etree import cElementTree
запросы на импорт
def parse_planetpy_rss ():
    "" "Анализирует первые 10 элементов из http://planetpython.org/rss20.xml
    "" "
    response = requests.get ('http://planetpython.org/rss20.xml')
    parsed_xml = cElementTree.fromstring (response.content)
    items = []
    для узла в parsed_xml.iter ():
        если node.tag == 'item':
            item = {}
            для item_node в списке (узле):
                если item_node.tag == 'title':
                    item ['title'] = item_node.text
                если item_node.tag == 'ссылка':
                    item ['ссылка'] = item_node.text
            items.append (элемент)
    вернуть товары [: 10]
  

Я использую запросов библиотеки для http (s) вещей в python. Я не обрабатываю никаких исключений, чтобы избежать перегрузки кода.Вот как выглядит представление Django:

  ТОКЕН = ''
TelegramBot = telepot.Bot (ТОКЕН)
def _display_help ():
    вернуть render_to_string ('help.md')
def _display_planetpy_feed ():
    return render_to_string ('feed.md', {'items': parse_planetpy_rss ()})
класс CommandReceiveView (Просмотр):
    def post (self, request, bot_token):
        если bot_token! = ТОКЕН:
            return HttpResponseForbidden ('Недействительный токен')
        commands = {
            '/ start': _display_help,
            'help': _display_help,
            'feed': _display_planetpy_feed,
        }
        пытаться:
            полезная нагрузка = json.загружает (request.body.decode ('utf-8'))
        кроме ValueError:
            return HttpResponseBadRequest ('Неверное тело запроса')
        еще:
            chat_id = полезная нагрузка ['сообщение'] ['чат'] ['идентификатор']
            cmd = payload ['message']. get ('text') # команда
            func = commands.get (cmd.split () [0] .lower ())
            если func:
                TelegramBot.sendMessage (chat_id, func (), parse_mode = 'Markdown')
            еще:
                TelegramBot.sendMessage (chat_id, 'Я вас не понимаю, сэр!')
        вернуть JsonResponse ({}, статус = 200)
    @method_decorator (csrf_exempt)
    def dispatch (self, request, * args, ** kwargs):
        вернуть super (CommandReceiveView, self) .dispatch (запрос, * аргументы, ** kwargs)
  

CommandReceiveView — это место, где творится чудо. Он получает запрос POST и обрабатывает его соответствующим образом в соответствии с командой. Полный исходный код доступен здесь. Взгляните на новый вызов API — sendMessage .Вы можете использовать его, когда хотите отправить что-то пользователю, указав chat_id и content. Идентификатор чата — это уникальный идентификатор разговора между пользователем и ботом. Когда вы вызываете getUpdates , вы видите его на каждом объекте Update. Но в Telegram есть ограничение для ботов, которое запрещает им отправлять сообщения пользователю, если конкретный пользователь не инициировал разговор с ботом (защита от спама).

Надеюсь, вы уже клонировали мое репо и запустили приложение django. Пришло время протестировать наше веб-приложение.Чтобы смоделировать взаимодействие между нашим приложением и службой Telegram API, я буду использовать расширение Chrome, которое называется Postman.

Postman — отличный инструмент, который помогает вам тестировать ваши приложения, отправляя запросы GET / POST / DELETE / PUT и т. Д. На определенный URL. Мы собираемся отправить запрос POST на наш CommandReceiveView и посмотреть, как он будет его обрабатывать.

Запустите веб-приложение, выполнив команду runserver. Целевой URL публикации:

http: // 127.0.0.1: 8000 / планета / b …

, где BOT_TOKEN следует заменить на данный ключ токена доступа.

Тело запроса можно получить из одного из объектов Update, которые мы получили при вызове метода getUpdates . Взгляните на скриншоты:

Давайте предоставим команду feed для нашего POST URL.

На скриншотах видно, что Telegram-бот правильно обработал наш запрос. Следующим шагом будет развертывание приложения и установка сертификата SSL для настройки веб-перехватчика.

Часть 2 — Как развернуть бота Telegram

Ссылки:

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *