Одним днём мы, редакция pythonist.ru, от нечего делать, стали кидать друг другу задачки и смотреть, кто быстрее решит. В какой-то момент нам пришла в голову идея автоматизировать этот процесс. Нам понадобился бот, который отправлял бы нам случайные задачки, а мы бы уже их наперегонки решали.
Итак, что мы имеем:
Следовательно, нам нужно написать на python что-то, что будет отправлять нам задачки прямо в чат. Источником задач мы, конечно же, взяли наш цикл статей по проекту Эйлера. Он ещё только в процессе заполнения, но его вполне можно использовать для наших задач.
Теперь, нужно разобраться с библиотеками, которыми мы будем пользоваться при написании бота. Ими станут:
Итак, приступим, для начала необходимо в новом проекте установить необходимые библиотеки:
pip install pytelegrambotapi pip install beautifulsoup4
Как мы видим, библиотеки установлены, и можно продолжать начатое. Следующим шагом мы создадим самого бота. Сделаем это с помощью @BotFather в самом telegram.
Отлично, бот создан, самое веселое ждет нас впереди, начинаем писать бота. Где писать — выбор каждого, главное, что внутри.
В последнем сообщении от BotFather, мы получили токен нашего бота, им нельзя делиться, так как это ключ к боту, позволяющий делать с ним всё что угодно.
Для начала нам нужно подключить бота к нашему python-коду, напишем следующее:
import telebot TOKEN = 'СЮДА ПИШЕМ ТОКЕН' bot = telebot.TeleBot(TOKEN)
Таким образом, наш скрипт будет понимать, с чем он работает, и отправлять запросы именно через нашего бота. Повторюсь, что очень важно не показывать никому свой токен, это может стоить вам бота.
Для того, чтобы убедиться, что всё в порядке, напишем небольшую функцию, для обработки команды ‘/start’. Telebot предоставляет удобные инструменты для обработки сообщений, собственно поэтому мы его и используем.
Итак, напишем декоратор, а потом разберемся, что к чему.
@bot.message_handler(commands=['start']) def command_hello(message): bot.reply_to(message, "Привет, если вы видите это сообщение, значит я работаю так, как надо:)") while True: # Для постоянной работы bot.polling()
Честно, даже с первого раза получилось. А теперь давайте разбираться что и как работает.
Первой строкой мы обратились к декоратору message_handler, он обрабатывает все входящие сообщения, если не передать ему никаких параметров. Мы же передали ему commands=[‘start’]. Это значит, что он будет реагировать только на сообщения-команды (начинающиеся со слэша), а в нашем случае, только на команду /start. Другие сообщения его не интересуют.
Затем мы прописываем функцию, которую декорируем, и говорим нашему боту, чтоб отвечал на сообщение ‘/start’ неким сообщением.
Последние две строчки нужны для того, чтобы бот работал постоянно, пока запущен. Просто оборачиваем bot.polling() в бесконечный цикл.
Бот работает, надо разобраться с тем, как мы будем получать задачи.
Для этих целей отлично подойдет BS4, который мы сразу установили. Это жутко удобная библиотека для парсинга совершенно любых сайтов, все зависит от скилла.
Но перед тем, как отдать сайт на съедение beautifulsoup, мы должны получить его html-код, делается это очень просто, импортируем встроенную библиотеку urllib, и отдаем ей url нашего сайта.
import urllib site = urllib.request.urlopen(‘https://pythonist.ru/spisok-zadach-proekt-ejlera-s-resheniyami/‘).read()
Передадим библиотеке beautifulsoup наш html-код, записанный в переменную site и, обработав улучшалкой beautifulsoup.prettify(), выведем полученный результат, чтобы убедиться, что все идет по плану.
soup = bs4.BeautifulSoup(site) print(soup.prettify())
На выводе мы получим огромное полотно кода, среди которого нас интересует только вот этот кусок:
<div class="entry-content">
<p>
<a href="https://pythonist.ru/zadacha-1-proekt-ejlera/">
Задача 1 «Числа, кратные 3 или 5»
</a>
<br/>
<a href="https://pythonist.ru/zadacha-2-chetnye-chisla-fibonachchi/">
Задача 2 «Четные числа Фибоначчи»
</a>
<br/>
<a href="https://pythonist.ru/zadacha-2-summa-czifr-faktoriala/">
Задача 20 «Сумма цифр факториала»
</a>
<br/>
<a href="http://pythonist.ru/zadacha-21-druzhestvennye-chisla/">
Задача 21 «Дружественные числа»
</a>
<br/>
<a href="http://pythonist.ru/zadacha-23-neizbytochnye-summy/">
Задача 23 «Неизбыточные суммы»
</a>
<br/>
<a href="http://pythonist.ru/zadacha-24-slovarnye-perestanovki/">
Задача 24 «Словарные перестановки:
</a>
</p>
</div>
<!-- .entry-content -->
Именно тут хранятся нужные нам ссылки на задачи, а мы находимся всё ближе к своей цели. Теперь нам нужно достать эти ссылки, чтобы у нас была возможность отправлять их. Для этого немного переписываем предыдущий код, не переживайте, без объяснений не останетесь:)
site = urllib.request.urlopen('https://pythonist.ru/spisok-zadach-proekta-ejlera-s-resheniyami/').read() soup = bs4.BeautifulSoup(site) raw_excersises = soup.find('div', {"class":'entry-content'}) #забираем интересующий нас кусок кода excersises = raw_excersises.find_all('a') links_to_excersises = [] for i in range(len(excersises)): links_to_excersises.append(excersises[i].get('href')) print('I have a list')
Что происходит в этом коде:
У этого кода есть один недостаток — при добавлении новой задачи на сайт, придется перезапускать бота, чтобы он заново спарсил список. Но так он работает намного быстрее, так как парсинг — дело долгое.
Ну все, осталось самое простое — по запросу выбрасывать ссылку на случайную задачу в чат. Для этого напишем декоратор-обработчик команды, назовем ее /task.
import random @bot.message_handler(commands=['task']) def send_task(message): link_to_send = random.choice(links_to_excersises) bot.reply_to(message, f'Окей, решайте вот эту задачу — {link_to_send}')
Тут особо сложного ничего нет, пройдемся по порядку:
Мы молодцы, бот написан и работает прекрасно. Однако, вы можете улучшить действующий функционал. Для закрепления материала попробуйте, например, сделать так, чтобы бот отправлял не ссылку на задачу, а сам текст задачи. Мы уверены, что вы справитесь. Ну и куда же без полного кода нашего бота, развлекайтесь!
import telebot import bs4 import urllib import random site = urllib.request.urlopen('https://pythonist.ru/spisok-zadach-proekta-ejlera-s-resheniyami/').read() soup = bs4.BeautifulSoup(site) raw_excersises = soup.find('div', {"class":'entry-content'}) #забираем интересующий нас кусок кода excersises = raw_excersises.find_all('a') links_to_excersises = [] for i in range(len(excersises)): links_to_excersises.append(excersises[i].get('href')) print('I have a list') TOKEN = 'да-да, тут должен быть токен' bot = telebot.TeleBot(TOKEN) @bot.message_handler(commands=['start']) def command_hello(message): bot.reply_to(message, "Привет, если вы видите это сообщение, значит я работаю так, как надо:)") @bot.message_handler(commands=['task']) def send_task(message): link_to_send = random.choice(links_to_excersises) bot.reply_to(message, f'Окей, решайте вот эту задачу — {link_to_send}') while True: # Для постоянной работы bot.polling()
При анализе данных часто требуется быстро найти абсолютное значение набора чисел. Для выполнения этой задачи…
Pydantic - это мощная библиотека проверки данных и управления настройками для Python, созданная для повышения…
Python предлагает набор библиотек, удовлетворяющих различные потребности в визуализации, будь то академические исследования, бизнес-аналитика или…
В Python для представления данных в двоичной форме можно использовать байты. Из этой статьи вы…
В этой статье рассказывается о том, что такое Werkzeug и как Flask использует его для…
При работе с датами часто возникает необходимость прибавлять к дате или вычитать из нее различные…