Представьте себе ситуацию: вы внимательно следите за определённым продуктом на Яндекс.Маркете и хотите моментально получить уведомление, как только его цена изменится в желаемую сторону. Или, возможно, вы являетесь владельцем интернет-магазина и стремитесь постоянно отслеживать динамику цен конкурентов, чтобы оперативно реагировать и сохранять свою конкурентоспособность на рынке. В обоих этих случаях, а также во множестве других сценариев, Discord-бот для мониторинга цен станет вашим незаменимым цифровым помощником, работающим 24/7. В рамках этой подробной статьи мы детально разберём процесс создания такого многофункционального бота.

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

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

  • Анализ конкурентных предложений для онлайн-агрегаторов: Если вы работаете с платформой, которая собирает и сравнивает предложения разных продавцов, наш бот станет важным инструментом для отслеживания и анализа цен. Он будет автоматически мониторить изменения цен у ваших поставщиков, сравнивать их с предложениями конкурентов и своевременно информировать вас о необходимости корректировки ценовой политики. Это позволит вам предлагать лучшие условия для клиентов и поддерживать конкурентоспособность вашей платформы.

Что мы будем делать? Подробный план действий

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

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

  • Разработка основного функционала Discord-бота
    Здесь мы сосредоточимся на написании базового кода, обеспечивающего подключение к Discord и реализацию основных команд взаимодействия.

  • Внедрение системы мониторинга цен
    На этом этапе мы интегрируем в нашего бота механизмы для сбора и анализа информации о ценах на товары с различных веб-ресурсов, используя специализированные библиотеки для обработки HTTP-запросов и извлечения данных из HTML-структур.

  • Запуск нашего бота в облаке для работ 24/7

    В этом нам поможет Amvera Cloud, где предоставляется возможность развернуть проект используя git push или просто перетянув файлы в интерфейсе. Помимо этого, есть и другие преимущества при использовании Amvera:

    • Удобная доставка обновлений кода через git. Обновление проекта на проде делается всего тремя командами в вашей IDE. Это проще, чем настройка VPS.

    • Вам не нужно делать никаких дополнительных настроек, приложение можно развернуть буквально за 5 минут. Заполняете пару полей в конфигурации, загружаете файлы, и все само настраивается и запускается.

    • Бесплатный баланс при регистрации - 111 рублей.

    • Если вы остановите проект, деньги не списываются и данные не теряются. Вы платите только за работающее приложение.

Но хватит рекламы, приступим к самому важному - разработке бота.

Подготовка окружения

1. Установка Python и необходимых библиотек

Для начала убедимся, что у нас установлен Python версии 3.8 или выше. Если Python ещё не установлен, загрузите его с официального сайта.
После установки откройте терминал и выполните команду:

python --version

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

Создадим и активируем виртуальное окружение:

# Создаём виртуальное окружение 
python -m venv venv 
# Активация виртуального окружения 
# На Windows: 
	.\venv\Scripts\activate  
# На macOS и Linux: 
	source venv/bin/activate

После активации виртуального окружения вы увидите префикс (venv) в начале командной строки.

Теперь установим необходимые библиотеки:

pip install discord.py requests beautifulsoup4 python-dotenv

Разбор установленных библиотек

discord.py: Эта асинхронная библиотека Python предназначена для взаимодействия с API Discord. Она позволяет создавать Discord-ботов, которые могут подключаться к серверам, отправлять и получать сообщения, реагировать на команды пользователей и выполнять множество других задач.

requests: Простая и мощная библиотека для выполнения HTTP-запросов. Она используется для отправки запросов на веб-страницы с целью получения HTML-кода страниц с ценами товаров.

beautifulsoup4: Библиотека для парсинга HTML и XML документов. Она позволяет извлекать нужные данные из HTML-кода страниц, что необходимо для получения цен товаров.

python-dotenv: Эта библиотека загружает переменные окружения из файла .env, что особенно полезно для безопасного хранения конфиденциальной информации, такой как токены API, пароли и другие данные.

Создание и настройка Discord-бота

Создание структуры проекта

Начнем с создания папки для проекта и организации файлов:

# Создаём папку проекта 
mkdir PriceMonitorBot cd PriceMonitorBot  
# Создаём основной файл проекта 
touch main.py  
# Создаём файл для хранения конфиденциальной информации 
touch .env

Создание приложения на Discord

  1. Перейдите на портал разработчиков Discord.

  2. Войдите в свой аккаунт Discord, если вы еще этого не сделали.

  3. На странице портала нажмите кнопку "New Application" .

  4. В открывшемся окне введите название вашего приложения и нажмите "Create".

Создание бота в приложении

  1. После создания приложения вас перенаправит на страницу управления. В меню слева выберите вкладку "Bot".

  2. Нажмите кнопку "Add Bot" (Добавить бота).

  3. Подтвердите создание бота, нажав "Yes, do it!".

Получение токена

  1. На странице бота под заголовком "TOKEN" нажмите кнопку "Copy" (Скопировать).

  2. Это и есть ваш токен — длинная строка символов. Обращайтесь с ним осторожно, так как он является "ключом" доступа к вашему боту.

Важно: Никому не передавайте ваш токен. Если токен попадет в чужие руки, злоумышленники смогут управлять вашим ботом. Если вы случайно раскрыли токен, его можно сбросить, нажав кнопку "Regenerate" (Регенирация).

Чтобы добавить бота на ваш сервер:

  • В разделе "OAuth2" выберите "URL Generator".

  • Отметьте пункт "bot" в разделе "SCOPES".

  • В разделе "BOT PERMISSIONS" выберите нужные разрешения (например, "Send Messages").

  • Скопируйте сгенерированную ссылку и откройте её в браузере. Выберите сервер, на который хотите пригласить бота.

Настройка файла .env

Файл .env будет содержать переменные окружения, которые используются для настройки вашего бота. Эти переменные будут загружаться в коде из файла с помощью библиотеки python-dotenv. Откройте файл .env в любом текстовом редакторе и добавьте в него следующие строки:

DISCORD_TOKEN=YOUR_DISCORD_BOT_TOKEN

Замените YOUR_DISCORD_BOT_TOKEN на фактический токен вашего бота, который мы получили ранее в панели разработчика Discord.

Организация и защита .env файла

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

Создайте файл .gitignore в корне проекта и добавьте в него строку:

.env

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

Первая часть нашего кода — это импорт всех нужных библиотек. Здесь используются библиотеки, которые помогут нам взаимодействовать с Discord, отправлять HTTP-запросы и парсить HTML, а также управлять переменными окружения:

import discord 
import requests 
from bs4 import BeautifulSoup 
from discord.ext import commands, tasks 
from dotenv import load_dotenv import os
  1. discord: Эта библиотека необходима для работы с API Discord. Она предоставляет классы и методы для управления сервером Discord, ботами, каналами, сообщениями и другими сущностями. Мы будем использовать её для создания и управления нашим ботом.

  2. requests: Используется для отправки HTTP-запросов. Эта библиотека поможет нам получать HTML-страницы с сайтов, чтобы извлекать информацию о ценах.

  3. BeautifulSoup: Библиотека для парсинга HTML и XML. В нашем проекте она используется для поиска и извлечения данных о ценах из HTML-кода страниц товаров.

  4. discord.ext.commands и discord.ext.tasks: Эти модули из discord.ext помогают расширить возможности discord.py. Модуль commands позволяет создавать команды для нашего бота, а tasks — запускать повторяющиеся задачи.

  5. dotenvload_dotenv из этой библиотеки позволяет загружать переменные окружения из файла .env. Это удобный и безопасный способ хранения конфиденциальной информации, такой как токен нашего бота, без необходимости включать её прямо в код.

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

Загрузка переменных окружения

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

load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN')
  • load_dotenv(): Эта функция загружает все переменные окружения, определенные в файле .env, в текущую сессию Python. Это позволяет нам использовать их в коде, не раскрывая реальные значения.

  • TOKEN: Мы получаем значение токена нашего бота из переменной окружения DISCORD_TOKEN. Это значение нужно будет определить в файле .env перед запуском кода. Использование переменных окружения вместо жесткого кодирования токенов или других конфиденциальных данных делает код более безопасным.

Настройка бота и объявление глобальных переменных

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

intents = discord.Intents.default() 
intents.message_content = True 
bot = commands.Bot(command_prefix='!', intents=intents)  

tracked_items = {} 
notification_channel = None
  1. intents: Интенции (intents) — это способ управления тем, какие события бот будет получать от Discord. Использование интенций позволяет снизить нагрузку на бота и улучшить безопасность. Здесь мы используем Intents.default() для создания объекта с базовыми настройками. Установка intents.message_content = True позволяет боту получать содержимое сообщений, что необходимо для обработки команд.

  2. bot: Здесь мы создаем экземпляр бота с использованием класса commands.Bot. Параметр command_prefix='!' указывает, что все команды бота будут начинаться с символа !. Параметр intents=intents задает интенции для бота.

  3. tracked_items: Это словарь, в котором мы будем хранить URL отслеживаемых товаров и их текущие цены. Словарь — удобная структура данных для этой задачи, так как она позволяет легко добавлять, удалять и обновлять элементы.

  4. notification_channel: Переменная, в которой будет храниться ссылка на канал, в который бот будет отправлять уведомления о изменении цен. Изначально она установлена в None, и её нужно будет настроить с помощью специальной команды.

Функция для получения цены товара

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

def get_price(url): 
	headers = { 
			"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"}
	response = requests.get(url, headers=headers) 
	soup = BeautifulSoup(response.text, 'html.parser')
	
	price_tag = soup.find('span', {'class': 'price'}) 
	if price_tag: 
		price = 
		float(price_tag.text.replace('\u2009', '').replace('₽', '').replace(' ', '').strip()) 
		return price 
	return None
  1. headers: Установка заголовков, включая User-Agent, делает запросы более похожими на запросы от обычного веб-браузера. Это помогает избежать блокировок или ограничений со стороны сайтов.

  2. requests.get(url, headers=headers): Выполняет HTTP-запрос к указанному URL с указанными заголовками. Если сайт доступен, получаем HTML-код страницы.

  3. BeautifulSoup: Мы используем BeautifulSoup для парсинга полученного HTML. Он помогает нам легко найти нужные теги и извлечь из них информацию.

  4. price_tag: Мы ищем первый элемент с тегом <span> и атрибутом class="price". Это упрощенное предположение, что цена на странице отображается именно в таком формате. В реальном проекте формат HTML может отличаться, и вам, возможно, придётся адаптировать этот код для конкретного сайта.

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

Реализация команд бота

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

  1. Добавление товара в отслеживание

@bot.command() 
async def track(ctx, url: str):     
	price = get_price(url)     
	if price:         
		tracked_items[url] = price        
			await ctx.send(f"Товар добавлен в отслеживание.Цена:{price}₽")
	else:         
		await ctx.send("Не удалось получить цену для этого товара.")
- **@bot.command()**: Декоратор, который регистрирует функцию как команду бота. Название функции (`track`) будет использоваться как команда, которую нужно отправить боту.
- **track(ctx, url: str)**: Эта команда принимает URL товара и добавляет его в список отслеживаемых товаров, если удаётся получить его цену. `ctx` — это контекст команды, он предоставляет информацию о вызове команды, включая канал, пользователя и т.д.
  1. Удаление товара из отслеживания

@bot.command() 
async def untrack(ctx, url: str):     
  if url in tracked_items:         
  	del tracked_items[url]         
  	await ctx.send(f"Товар удален из отслеживания.")     
  else:         
  	await ctx.send("Этот товар не отслеживается.")`
- **untrack(ctx, url: str)**: Команда для удаления товара из списка отслеживаемых. Она проверяет, есть ли указанный URL в `tracked_items` и удаляет его, если он там есть.
  1. Просмотр списка отслеживаемых товаров

  @bot.command() 
  async def list(ctx):     
      if tracked_items:         
  	    message = "Отслеживаемые товары:\n"         
  		for url, price in tracked_items.items():             
  			message += f"{url} - Текущая цена: {price} ₽\n"        
  		await ctx.send(message)     
  	else:         
  		await ctx.send("Список отслеживаемых товаров пуст.")`
- **list(ctx)**: Команда для отображения всех товаров, которые бот отслеживает, вместе с их текущими ценами. Если список пуст, бот сообщает об этом.
  1. Установка канала для уведомлений

@bot.command() 
async def setchannel(ctx):     
	global notification_channel     
	notification_channel = ctx.channel    
	await ctx.send(f"Уведомления о изменении цен будут отправляться в канал: {ctx.channel.name}")`
c- **setchannel(ctx)**: Команда для установки текущего канала в качестве канала для отправки уведомлений о изменении цен. Эта команда запоминает канал, из которого была вызвана, и сохраняет его в глобальной переменной `notification_channel`.
  1. Обновление цен вручную

@bot.command()
async def update(ctx):
await ctx.send("Обновление цен...")
await price_check()

  
    - **update(ctx)**: Команда для ручного запуска проверки цен. Полезно для случаев, когда нужно немедленно узнать о изменениях цен.

### Задача для регулярной проверки цен

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

```python
@tasks.loop(minutes=60) 
async def price_check():     
	for url, old_price in tracked_items.items():         
		new_price = get_price(url)         
		if new_price and new_price != old_price:             
			tracked_items[url] = new_price             
			if notification_channel:                 
				await notification_channel.send(f"Цена на товар изменилась! Новая цена: {new_price} ₽ (Старая цена: {old_price} ₽)\n{url}")             
			else:                 
				print("Канал для уведомлений не установлен.")
  • @tasks.loop(minutes=60): Декоратор, который указывает, что функция price_check должна выполняться каждые 60 минут.

  • price_check(): Эта функция проходит по всем отслеживаемым товарам и проверяет их текущие цены. Если цена изменяется, бот обновляет её в словаре tracked_items и отправляет уведомление в установленный канал.

Запуск бота

Последний шаг — это запуск бота с использованием токена.

`@bot.event async def on_ready():     
	print(f'Logged in as {bot.user}')     
	price_check.start()  

bot.run(TOKEN)`
  • on_ready(): Событие, которое вызывается, когда бот успешно подключается к серверу Discord. Здесь мы выводим сообщение в консоль и запускаем задачу price_check.

  • bot.run(TOKEN): Запускает бота с указанным токеном. Токен должен быть определён в файле .env.

Теперь, когда мы настроили и протестировали нашего Telegram-бота на локальной машине, самое время запустить его в облаке, чтобы он был доступен 24/7. В этом шаге мы развернем бота на платформе Amvera, которая предоставляет удобные инструменты для хостинга приложений.

Регистрация в сервисе

  1. Создание аккаунта:

    • Перейдите на сайт Amvera и нажмите на кнопку "Регистрация".

    • Заполните все необходимые поля, включая номер телефона, и нажмите на кнопку "Отправить код".

    • Введите код, полученный в SMS, подтвердите, что вы не робот, и нажмите "Регистрация".

    • После этого подтвердите адрес электронной почты, перейдя по ссылке в письме.

    • Получите на баланс 111 руб. на тесты)

Создание проекта и размещение бота

  1. Создание нового проекта:

    • После входа на платформу, на главной странице нажмите на кнопку "Создать" или "Создать первый!".

    https://habrastorage.org/r/w1560/getpro/habr/upload_files/90a/00c/aa0/90a00caa0d20e5d56d26f898a5eb9fe2.png
  2. Настройка проекта:

    • Присвойте вашему проекту название (лучше на английском языке).

    • Выберите тарифный план. Для развертывания бота будет достаточно самого простого тарифа.

    • Начального баланса хватит для того, чтобы бот работал бесплатно и непрерывно в течение нескольких недель.

    https://habrastorage.org/r/w1560/getpro/habr/upload_files/3d0/1e7/14c/3d01e714ca77535ca452f7afa0ced4a2.png
  3. Подготовка кода для развертывания:

  • Amvera использует git для доставки кода в облако. Вам потребуется создать файл конфигурации amvera.yml, который подскажет облаку, как запускать ваш проект.

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

    • Укажите версию Python и путь до файла requirements.txt, который содержит все необходимые пакеты.

    • Укажите путь до основного файла вашего проекта, например main.py.

  • Хранение данных:

    • Если бот сохраняет данные на диск, они должны размещаться в папке data, чтобы избежать их потери при перезапуске.

  • Генерация и загрузка файла:

    • Нажмите "Generate YAML" для создания файла amvera.yml и загрузите его в корень вашего проекта.

Файл конфигурации amvera.yml служит для того, чтобы платформа Amvera знала, как правильно собрать и запустить ваш проект. Этот файл содержит ключевую информацию об окружении, зависимостях, а также инструкциях для запуска приложения.

Структура файла amvera.yml:

meta:
  environment: python  # Указывает, что проект использует Python в качестве окружения.
  toolchain:
    name: pip          # Определяет менеджер пакетов для установки зависимостей.
    version: "3.8"     # Задает версию Python для окружения проекта.

build:
  requirementsPath: requirements.txt  # Путь к файлу, где указаны все необходимые зависимости.

run:
  scriptName: app.py  # Основной файл вашего проекта, который будет запущен после сборки.
  persistenceMount: /data  # Директория для хранения постоянных данных.
  containerPort: 80    # Порт, на котором будет доступен ваш проект в контейнере.

Для того чтобы наш проект корректно работал в среде Amvera, важно указать все необходимые пакеты в файле requirements.txt. Этот файл определяет все зависимости Python, которые нужны для выполнения кода.

Вот так выглядит наш файл requirements.txt :

discord.py==2.2.3
requests==2.31.0
beautifulsoup4==4.12.2
python-dotenv==1.0.0

Инициализация и отправка проекта в репозиторий:

  • Инициализируйте git репозиторий в корне вашего проекта, если это еще не сделано:

    git init
  • Привяжите локальный репозиторий к удаленному на Amvera:

    git remote add amvera <https://git.amvera.ru/ваш_юзернейм/ваш_проект>
  • Добавьте и зафиксируйте изменения:

    git add .
    git commit -m "Initial commit"
  • Отправьте проект в облако:

    git push amvera master

Сборка и развертывание проекта:

  • После отправки проекта в систему, на странице проекта статус изменится на "Выполняется сборка".

https://habrastorage.org/r/w1560/getpro/habr/upload_files/ebb/8d7/7e3/ebb8d77e3a4c581c15a03843df3386d2.png
Статус сборки появится после загрузки всех файлов и коммита

После завершения сборки проект перейдет в стадию "Выполняется развертывание", а затем в статус "Успешно развернуто".

https://habrastorage.org/r/w1560/getpro/habr/upload_files/c75/56c/5f7/c7556c5f70e0992280694a346ba3f070.png
Среднее время сборки и запуска 5-10 минут. В момент запуска статус может гореть красным - это нормально. Главное смотреть ошибки в логе
Успешный запуск
Успешный запуск

Если проект не развернулся, проверьте логи сборки и логи приложения для отладки.

Если проект завис на этапе "Сборка", убедитесь в корректности файла amvera.yml.

Заключение

В этой статье мы рассмотрели процесс создания и развертывания Discord-бота для мониторинга цен на Яндекс.Маркете. Мы прошли путь от написания кода бота на Python до его размещения в облаке на платформе Amvera.

Ключевые моменты, которые мы охватили:

  • Разработка функционала бота для мониторинга цен

  • Настройка команд и обработка событий в Discord

  • Реализация автоматической проверки цен с заданным интервалом

  • Процесс регистрации и создания проекта на платформе Amvera

  • Подготовка проекта к развертыванию в облаке

  • Настройка и отправка кода в репозиторий Amvera

Автор: Алексей Пономарев


Релевантные статьи

Комментарии (9)


  1. Pitcentr0
    01.09.2024 14:47

    в сервисе n8n io можно сделать все тоже только без хостинга и кодинга, ах да, вам же хостинг нужно продать


    1. kirillkosolapov
      01.09.2024 14:47

      1. NoCode инструменты позволяют сделать далеко не все, что вы можете реализовать в коде. 2. Для работы 24/7 вам в любом случае нужен хостинг/облако. Но вы можете развернуть Python код на любом решении, которое вам нравится 3. Могу быть не прав, но мне показалось, что приведенный вами сервис немного для другого предназначен


    1. GermanAizek
      01.09.2024 14:47

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


      1. NikitinIlya Автор
        01.09.2024 14:47

        Сарафанное радио и конкурентная цена, это конечно хорошо. Но это далеко не всегда так работает. Да, если вы вышли на рынок лет 15 назад (или сейчас с чем-то, совсем неизвестным на рынке), это бы работало, но не для хостингов сейчас с их конкуренцией и ценами. И логично, что компании, которые платят по 643000-1152000 руб. за блоги, будут в статьях себя упоминать. Главное, для читателя, чтобы сама статья была ценна, и несла в себе что то новое и полезное. Если статья полезная, то есть в ней интегрированная реклама или нет, не так важно, а если статья плохая, то ей ничего не поможет