[Python, Программирование] Пишем телеграм-бота, который будет переводить интернет статьи в mp3-файлы
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Всем привет! В данной статье я поделюсь своей реализацией бота для telegram, который может переводить статьи из интернета в mp3-файлы. Для этого я буду использовать python 3.6 и соответствующие библиотеки. Итак, приступим.Для начала надо зарегистрировать своего бота в telegram. На хабре есть статья, в которой это подробно описано. Далее надо установить pip, на всякий случай прикрепляю ссылку на его установку. После установки менеджера пакетов устанавливаем библиотеки, которые помогут осуществить задуманное, выполняем в терминале:
pip install pyttsx3
pip install langdetect
pip install pydub
pip install bs4
pip install telebot
pip install PyTelegramBotAPI
Теперь надо создать три основных файла:bot.pyparser.pyvoice.pyВ них будет реализована логика работы приложения. bot.py отвечает непосредственно за работу бота, основные функции всех модулей вызываются в нем. В parser.py реализован парсинг, того что отправлено боту, в voice.py реализован функционал перевода данных после парсинга в аудиоформат. Смысл таков, боту приходит ссылка на статью из интернета, если она удовлетворяет условию(url-адрес ведет на контент, который написан с использованием тега <article>, а не содержащий просто набор текста), текст статьи парсится с помощью bs4 и средствами библиотеки pyttsx3 записывается в аудиофайл, который в дальнейшем конвертируется в mp3 и отправляется пользователю обратно сообщением. Все просто. Понеслась...bot.pyЯ использую декоратор message_handler, чтобы отвечать юзеру на вызов команды /start
import telebot
from voice import get_mp3_file, get_file_name
from parser import get_article_text, get_article_language, get_link
bot = telebot.TeleBot('TOKEN')
@bot.message_handler(commands=['start'])
def forward_message(message):
bot.send_message(message.from_user.id, "Привет, я перевожу статьи в аудиофайлы,"
"пришли мне ссылку на статью, "
"а я сброшу тебе mp3 файл.")
и на сообщения
is_running = False
@bot.message_handler(content_types=['text'])
def forward_message(message):
global is_running # Глобальная переменная для проверки в работе бот или нет
if not is_running:
link = get_link(message.text)
if link: # Проверка, что боту отправили ссылку, а не что-то другое
is_running = True
article_text = get_article_text(link)
article_language = get_article_language(article_text)
if article_language: # Проверка, что статья была распарсена и ее язык получен
bot.send_message(message.from_user.id, "Да, эта статья подходит.")
bot.send_message(message.from_user.id, f"Язык статьи - {article_language[0]}.")
bot.send_message(message.from_user.id, "Отправляю аудиофайл...")
file_name = get_file_name(link)
get_mp3_file(file_name, article_text, article_language[1])
bot.send_audio(message.from_user.id, audio=open(file_name, 'rb'))
else:
bot.send_message(message.from_user.id, "Данная статья не подходит,"
"попробуй прислать другую...")
is_running = False
else:
bot.send_message(message.from_user.id, "Нет, это не ссылка, попробуй "
"прислать ссылку на статью.")
else:
bot.send_message(message.from_user.id, "Я занят предыдущим запросом, "
"подожди немного...")
Глобальная переменная is_running и ее проверка нужна для того, чтобы не вызывать повторно основные функции бота до тех пор, пока они не закончат работу над предыдущим запросом. То есть, боту необходимо отправить аудиофайл или же дать ответ юзеру, что, что-то пошло не так и только потом принимать новый запрос на обработку. В переменной link я проверяю, что боту пришел действительно url-адрес, а в article_language, что статья была удачно распарсена и ее язык получен.
if link: # Проверка, что боту отправлена ссылка, а не что-то другое
is_running = True
article_text = get_article_text(link)
article_language = get_article_language(article_text)
parser.py
import requests
from bs4 import BeautifulSoup
from langdetect import detect
import re
def get_link(message_text):
# Ищем ссылку в отправленном боту сообщении
link_arr = re.findall(r'^https?:\/\/?[\w-]{1,32}'
r'\.[\w-]{1,32}[^\s@]*$', message_text)
if len(link_arr) > 0:
link = link_arr[0]
return link
return False
Чтобы проверить, что пользователь действительно отправил ссылку, я использую регулярное выражение в функции get_link. Если функция отработала и вернула url статьи, я иду дальше и получаю её текст, если вернулся False, бот посылает посылает сообщение: "Нет, это не ссылка, попробуй прислать ссылку на статью."
def get_article_text(link):
try:
# Получаем ответ от сервера, на который ведет ссылка
response = requests.get(link)
except requests.exceptions.ConnectionError:
return False
# Инициализируем парсер
parser = BeautifulSoup(response.content, 'html.parser')
try:
# Парсим статью по тегу <article>
article_text = parser.select_one('article').get_text(separator='. ')
except AttributeError:
return False
return article_text
Здесь я проверяю код ответа, использую для этого соответствующее исключение, если боту был отправлен несуществующий url. При вызове requests.exceptions.ConnectionError возвращается False, который в дальнейшем не пройдет проверку в get_article_language.Парсинг статьи осуществляется библиотекой BeautifulSoup4 по тегу <article>, с получением всего входящего в тег текста, с разделением через точку с пробелом. Это нужно для того, чтобы разделить слитные части текста, которые могут образоваться при парсинге, в итоге аудиофайл будет прочитан программой с более верной интонацией. get_article_text возвращает строку с содержимым статьи, либо False.
def get_article_language(article_text):
try:
language = detect(article_text) # Определяем язык статьи
except TypeError:
return False
if language == 'en':
return ['EN', ['en_GB']]
if language == 'ru':
return ['RU', ['ru_RU']]
return False
Язык статьи я определяю, используя библиотеку langdetect. Я выбрал в своей реализации всего лишь 2 языка: русский и английский, хотя можно было бы и больше. В функции возвращается либо массив, 0-ой элемент которого идет в отправку сообщения юзеру об языке статьи, а 1-й элемент используется в pyttsx3 для выбора языка чтеца, либо False, тогда бот посылает сообщение: "Данная статья не подходит, попробуй прислать другую…".voice.py
import pyttsx3
from pydub import AudioSegment
import re
def engine_settings(engine, article_language):
voices = engine.getProperty('voices')
engine.setProperty('rate', 185) # Выставляем скорость чтения голоса
for voice in voices:
if voice.languages == article_language and \
voice.gender == 'VoiceGenderMale':
return engine.setProperty('voice', voice.id) # Выбираем подходящий голос
def get_mp3_file(file_name, article_text, article_language):
engine = pyttsx3.init()
engine_settings(engine, article_language) # Применение настроек голоса
engine.save_to_file(article_text, file_name) # Сохранение текста статьи в аудиофайл
engine.runAndWait()
convert_file_to_mp3(file_name) # Конвертация в mp3 формат
def convert_file_to_mp3(file_name):
converter = AudioSegment
converter_file = converter.from_file(file_name)
converter_file.export(file_name, format="mp3")
def get_file_name(link):
# Название файла - ссылка на статью
file_name = re.split(r'^https?:\/\/?', link)[1]
for symbols_in_file_name in ['/', '.', '-']:
# Замена символов в названии файла на '_', чтобы сохранить файл в OS
file_name = file_name.replace(symbols_in_file_name, '_')
file_name = file_name+'.mp3' # Сохраняем файл изначально в mp3 формате
return file_name
Для создания аудиофайла я использую библиотеку pyttsx3 как указано было ранее, а для конвертации в mp3 библиотеку pydub. Сначала я задаю настройки в engine_settings, выставляю скорость чтения, в зависимости от языка статьи использую русско-говорящего или англо-говорящего чтеца мужского пола и выбираю его голос.В get_mp3_file я применяю настройки из engine_settings, сохраняю полученный текст статьи после парсинга в аудиофайл(в get_file_name указываю mp3, но по факту pyttsx3 дает другой формат и в обычных проигрывателях, полученный файл не воспроизводится, поэтому в дальнейшем его надо конвертировать с помощью AudioSegment). После выполнения engine.runAndWait и дальнейшей конвертации в mp3, файл сохранится в текущей директории проекта.Теперь бот может отправить аудиофайл юзеру. Прикрепляю видео работы бота.Запускаем
python bot.py
Извините, данный ресурс не поддреживается. :( Извините, данный ресурс не поддреживается. :( Конечно, у меня получился неидеальный парсинг, причем завязанный на тег <article> и голос в pyttsx3 в некоторых моментах может быть неслушабельным, но задумка по моему мнению неплохая и к тому же работающая. Спасибо за внимание.
===========
Источник:
habr.com
===========
Похожие новости:
- [Python, Тестирование мобильных приложений] Robot Framework для автоматизации тестирования: ограничения и плюшки
- [Python, Программирование] Json api сервис на aiohttp: middleware и валидация
- [Программирование, Функциональное программирование, TypeScript] Функциональное программирование на TypeScript: Option и Either
- [Программирование, Анализ и проектирование систем, Проектирование и рефакторинг] Эффективная конструкция агрегатов. Понимание через исследование (перевод)
- [Мессенджеры, Open source, Системное администрирование, PHP, Программирование] Введение в метрики для PHP разработчика
- [Open source, Python, IT-инфраструктура, Хранение данных, Хранилища данных] HDB++ TANGO Archiving System (перевод)
- [Программирование, Java, Kotlin, Gradle, Микросервисы] Шаблон Kotlin микросервисов
- [Ненормальное программирование, Ruby, Программирование, Go] Запускаем скрипты Ruby из Go Lang
- [Программирование, Удалённая работа] Дружим WSL и VSCode через Tailscale и упрощаем работу в сети (перевод)
- [Гаджеты] Лидеры сборов китайского «Кикстартера» от Xiaomi: лазерная кепка, ушечистка с камерой и электрошвабра
Теги для поиска: #_python, #_programmirovanie (Программирование), #_python3, #_telegram, #_bots, #_telegramapi, #_pyttsx3, #_pydub, #_beautifulsoup, #_parsing, #_articles, #_websites, #_python, #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:05
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Всем привет! В данной статье я поделюсь своей реализацией бота для telegram, который может переводить статьи из интернета в mp3-файлы. Для этого я буду использовать python 3.6 и соответствующие библиотеки. Итак, приступим.Для начала надо зарегистрировать своего бота в telegram. На хабре есть статья, в которой это подробно описано. Далее надо установить pip, на всякий случай прикрепляю ссылку на его установку. После установки менеджера пакетов устанавливаем библиотеки, которые помогут осуществить задуманное, выполняем в терминале: pip install pyttsx3
pip install langdetect pip install pydub pip install bs4 pip install telebot pip install PyTelegramBotAPI import telebot
from voice import get_mp3_file, get_file_name from parser import get_article_text, get_article_language, get_link bot = telebot.TeleBot('TOKEN') @bot.message_handler(commands=['start']) def forward_message(message): bot.send_message(message.from_user.id, "Привет, я перевожу статьи в аудиофайлы," "пришли мне ссылку на статью, " "а я сброшу тебе mp3 файл.") is_running = False
@bot.message_handler(content_types=['text']) def forward_message(message): global is_running # Глобальная переменная для проверки в работе бот или нет if not is_running: link = get_link(message.text) if link: # Проверка, что боту отправили ссылку, а не что-то другое is_running = True article_text = get_article_text(link) article_language = get_article_language(article_text) if article_language: # Проверка, что статья была распарсена и ее язык получен bot.send_message(message.from_user.id, "Да, эта статья подходит.") bot.send_message(message.from_user.id, f"Язык статьи - {article_language[0]}.") bot.send_message(message.from_user.id, "Отправляю аудиофайл...") file_name = get_file_name(link) get_mp3_file(file_name, article_text, article_language[1]) bot.send_audio(message.from_user.id, audio=open(file_name, 'rb')) else: bot.send_message(message.from_user.id, "Данная статья не подходит," "попробуй прислать другую...") is_running = False else: bot.send_message(message.from_user.id, "Нет, это не ссылка, попробуй " "прислать ссылку на статью.") else: bot.send_message(message.from_user.id, "Я занят предыдущим запросом, " "подожди немного...") if link: # Проверка, что боту отправлена ссылка, а не что-то другое
is_running = True article_text = get_article_text(link) article_language = get_article_language(article_text) import requests
from bs4 import BeautifulSoup from langdetect import detect import re def get_link(message_text): # Ищем ссылку в отправленном боту сообщении link_arr = re.findall(r'^https?:\/\/?[\w-]{1,32}' r'\.[\w-]{1,32}[^\s@]*$', message_text) if len(link_arr) > 0: link = link_arr[0] return link return False def get_article_text(link):
try: # Получаем ответ от сервера, на который ведет ссылка response = requests.get(link) except requests.exceptions.ConnectionError: return False # Инициализируем парсер parser = BeautifulSoup(response.content, 'html.parser') try: # Парсим статью по тегу <article> article_text = parser.select_one('article').get_text(separator='. ') except AttributeError: return False return article_text def get_article_language(article_text):
try: language = detect(article_text) # Определяем язык статьи except TypeError: return False if language == 'en': return ['EN', ['en_GB']] if language == 'ru': return ['RU', ['ru_RU']] return False import pyttsx3
from pydub import AudioSegment import re def engine_settings(engine, article_language): voices = engine.getProperty('voices') engine.setProperty('rate', 185) # Выставляем скорость чтения голоса for voice in voices: if voice.languages == article_language and \ voice.gender == 'VoiceGenderMale': return engine.setProperty('voice', voice.id) # Выбираем подходящий голос def get_mp3_file(file_name, article_text, article_language): engine = pyttsx3.init() engine_settings(engine, article_language) # Применение настроек голоса engine.save_to_file(article_text, file_name) # Сохранение текста статьи в аудиофайл engine.runAndWait() convert_file_to_mp3(file_name) # Конвертация в mp3 формат def convert_file_to_mp3(file_name): converter = AudioSegment converter_file = converter.from_file(file_name) converter_file.export(file_name, format="mp3") def get_file_name(link): # Название файла - ссылка на статью file_name = re.split(r'^https?:\/\/?', link)[1] for symbols_in_file_name in ['/', '.', '-']: # Замена символов в названии файла на '_', чтобы сохранить файл в OS file_name = file_name.replace(symbols_in_file_name, '_') file_name = file_name+'.mp3' # Сохраняем файл изначально в mp3 формате return file_name python bot.py
=========== Источник: habr.com =========== Похожие новости:
Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 08:05
Часовой пояс: UTC + 5