Skip to content

Repository files navigation

Как написать tg-bot, выдающий оценки из ведомости

Давайте опишем простым языком идею, которую мы хотим реализовать:

  • Есть ведомость с оценками за курс по Питону. На двух листах содержатся оценки, как за отдельные элементы контроля, так и посчитанные по формулам.

  • Есть две группы студентов, которым бы хотелось быстро и просто узнавать свои баллы (не все, а ключевые - средняя, за Кр, итоговая), не заходя в ведомость.

  • Мы хотим сделать Бота, который по введенным "Фамилии и имени" выдавал бы оценки.

Чтобы это реализовать, мы будем использовать библиотеку pandas для работы с данными из Excel и библиотеку telebot для взаимодействия с Telegram API.

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

  1. Что мы хотим получить.
  2. Как это реализовать.

Пункт 1. Импортируем библиотеки

importtelebotimportpandasaspd

telebot: это библиотека для работы с Telegram Bot API, которая позволяет создавать ботов для Telegram.
pandas: это библиотека для работы с данными, которая предоставляет структуры данных и функции для анализа данных. В данном случае мы используем ее для работы с Excel-файлом.

Пункт 2. Создаем бота.

Сразу важное отступление!

Чтобы создать собственного бота нам нужен бот.

@BotFather отлично в этом поможет. Парой команд мы получаем наш Bot API, называем его, выбираем картиночку, добавляем описание и прочее. И вот потом имеем строчку, свяживающую наш последующий код с тем ботом, который оживет и реально начнет работать.
Прописываем нашего бота, где много букв и цифр - этот токен используется для доступа к HTTP API и взаимодействия с телеграмом.

bot=telebot.TeleBot('4834753573-sbjgbygbajgevaarv - и что-то подобное -сюда вы пишете свой токен')

Пункт 3. Про данные.

Создаем словарь для хранения данных пользователей.

user_data= {}

Поскольку у нас есть таблица в Excel, в которой указаны данные по двум группам, имеются два листа с названиями "Чистмат" и "Совбак".
Мы хотим создать функцию, которая загружает данные из Excel-файла в зависимости от выбранного направления (Чистмат или Совбак). Она использует pandas.read_excel для чтения данных из указанного листа.

defload_data(department):
sheet_name='Чистмат'ifdepartment=='Чистмат'else'Совбак'returnpd.read_excel('Ведомость (Python, матфак).xlsx',
sheet_name=sheet_name)

Пункт 4. Начинаем.

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

@bot.message_handler(commands=['start'])defsend_welcome(message):
bot.reply_to(message,
"Привет! Если хочешь узнать оценки по Питону, ""напиши пожалуйста, ты Чистмат или Совбак?")
user_data[message.chat.id] = {}

Пункт 5. Выбираем группу - Чистмат или Совбак.

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

@bot.message_handler(func=lambdamessage: message.text.lower() in ['чистмат', 'совбак'])defget_department(message):
ifmessage.chat.idnotinuser_data:
user_data[message.chat.id] = {}
department=message.text.lower().capitalize()
user_data[message.chat.id]['department'] =department# Это так мы листочек нужный выбираемuser_data[message.chat.id]['data'] =load_data(department)
bot.reply_to(message, "Отлично, напиши пожалуйста фамилию и имя.")

Пункт 6. Получаем данные из таблицы.

После ввода Фамилии и имени в загруженной таблице ищем данные студента с помощью метода str.contains, который проверяет, содержится ли введенная строка в столбце 'ФИО'.
Еще пропишем такое: в случае ошибки (например, если данные не загружены) бот отправляет сообщение об ошибке.

@bot.message_handler(func=lambdamessage:message.chat.idinuser_dataand'data'inuser_data[message.chat.id])defget_grades(message):
fio=message.text.strip()
data=user_data[message.chat.id]['data']
try:
student_data=data[data['ФИО'].str.contains(fio,
case=False, na=False)]
exceptExceptionase:
bot.reply_to(message, f"Произошла ошибка: {e}")
return

Пункт 7. Ответ от бота, делаем его красивым.

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

Добавим такое условие для автоматов: Если итоговая оценка равна 8.0, добавляется сообщение о перезачете.
И соответственно условие: если данные не найдены, бот отправляет сообщение о том, что студент не найден.

ifnotstudent_data.empty:
response=""forindex, rowinstudent_data.iterrows():
response+= (
f"ФИО: {row['ФИО']}\n"f"""Средняя за ДЗ: {round(row['Средняя ДЗ'], 2)ifnotpd.isna(row['Средняя ДЗ'])else'балл пока не стоит'}\n"""f"""Средняя за СР: {round(row['Средняя СР'], 2)ifnotpd.isna(row['Средняя СР'])else'балл пока не стоит'}\n"""f"""Контрольная: {round(row['КР'], 2)ifnotpd.isna(row['КР'])else'балл пока не стоит'}\n"""f"""Проект: {round(row['Проект'], 2)ifnotpd.isna(row['Проект'])else'балл пока не стоит'}\n"""f"""Экзамен: {round(row['Экзамен'], 2)ifnotpd.isna(row['Экзамен'])else'балл пока не стоит'}\n"""f"""Итоговая: {round(row['Итоговая'], 2)ifnotpd.isna(row['Итоговая'])else'балл пока не стоит'}\n\n"""
)
ifnotpd.isna(row['Итоговая']) androw['Итоговая'] ==8.0:
response+="Курс был перезачтён\n\n"bot.reply_to(message, response.strip())

Пункт*

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

bot.reply_to(message,
"Желаю тебе отлично сдать проект, ""экзамен и просто выучить Питон!")
bot.reply_to(message,
"Если узнать еще чьи-то оценки, то напиши, ""этот человек Чистмат или Совбак?")
else:
bot.reply_to(message, "Студент с такой фамилией не найден.")

Они отправляются в отдельных сообщениях сразу после сообщения с результатами.

Пункт 8. Для всяких неожиданностей.

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

@bot.message_handler(func=lambdamessage: True)defhandle_unexpected_message(message):
ifmessage.chat.idnotinuser_data:
bot.reply_to(message, "Привет! Если хочешь узнать оценки по Питону, ""напиши пожалуйста, ты Чистмат или Совбак?")
else:
bot.reply_to(message, "Пожалуйста, напиши фамилию и имя.")

Пункт 9. Две строки или как заставить всё работать.

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

if__name__=='__main__':
bot.polling()

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

Пример диалога с ботом:

MathFacPython_marks: Привет! Если хочешь узнать оценки по Питону, напиши пожалуйста, ты Чистмат или Совбак?
Софья: Совбак
MathFacPython_mark: Отлично, напиши пожалуйста фамилию и имя.
Софья: Никитина Софья
MathFacPython_marks:
ФИО: Никитина Софья Витальевна
Средняя за ДЗ: 9.0
Средняя за СР: 6.06
Контрольная: 3.0
Проект: балл пока не стоит
Экзамен: балл пока не стоит
Итоговая: 2.71
MathFacPython_marks: Желаю тебе отлично сдать проект, экзамен и просто выучить Питон!
MathFacPython_marks: Если узнать еще чьи-то оценки, то напиши, этот человек Чистмат или Совбак?

Итог. Созданный бот.

У нас была идея - с помощью бота сделать получение данных удобным. Наш код создает Telegram-бота, который позволяет пользователям запрашивать оценки студентов по двум направлениям (Чистмат и Совбак). Он использует библиотеку pandas для работы с данными из Excel и библиотеку telebot для взаимодействия с Telegram API.
За 9 шагов мы реализовали нашу идею на Питоне, опробовали, учли возможные неожиданные сообщения со стороны пользователя, всё прописали и отпустили в жизнь.

About

This bot will send you marks, if you're Math Faculty student

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages