Ошибка IndexError: "list index out of range" в тг-боте
Есть код:
from telebot import TeleBot, types
from bs4 import BeautifulSoup
import random as rnd
import requests
import token
TOKEN = token.token
bot = TeleBot(TOKEN)
@bot.message_handler(commands=["start"])
def handle_start(message):
global city
bot.send_message(message.chat.id, "Привет, давай пройдем небольшую регистрацию!")
bot.send_message(message.chat.id, "Введи город в котором ты живешь(это нужно для определения погоды в твоем городе)")
city = message.text.lower()
@bot.message_handler(commands=["menu"])
def handle_menu(message):
keyboard = types.InlineKeyboardMarkup()
info_b = types.InlineKeyboardButton('Информация?', callback_data='qwerty')
weather_b = types.InlineKeyboardButton('Погода❄️', callback_data='Weather')
keyboard.add(info_b, weather_b)
bot.send_message(message.chat.id,f"Привет, {message.from_user.first_name}, это менюшка", reply_markup=keyboard)
def check_weather(city):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
}
responce = requests.get(f"https://www.google.com/search?q=погода+в+{city}", headers=headers)
print(responce)
soup = BeautifulSoup(responce.text, "html.parser")
temperature = soup.select("#wob_tm")[0].getText()
title = soup.select("#wob_dc")[0].getText()
humidity = soup.select("#wob_hm")[0].getText()
time = soup.select("#wob_dts")[0].getText()
wind = soup.select("#wob_ws")[0].getText()
print(time)
print(title)
print(f"Температура: {temperature}C")
print(f"Влажность: {humidity}")
print(f"Ветер: {wind}")
return temperature
@bot.callback_query_handler(func=lambda callback: True)
def callback_message(callback):
if callback.data == "Weather":
bot.send_message(callback.message.chat.id, text=f"{check_weather(city)}")
if __name__ == '__main__':
bot.polling(none_stop=True)
Возникает ошибка после нажатия на кнопку Погода:
Ошибка temperature = soup.select("#wob_tm")[0].getText() IndexError: list index out of range
Ответы (1 шт):
Во-первых, в глобальную переменную вы записываете команду, только что введённую пользователем. А значит, в объявленную глобальную переменную записывается не город, а команда /start
.
Для того, чтобы это исправить существует метод register_next_step_handler()
.
@bot.message_handler(commands=["start"])
def handle_start(message):
bot.send_message(message.chat.id, "Привет, давай пройдем небольшую регистрацию!")
city_message = bot.send_message(
message.chat.id,
"Введи город в котором ты живешь(это нужно для определения погоды в твоем городе)")
bot.register_message_handler(city_message, get_city)
def get_city(message):
city = message.text.lower()
...
Уже в функции get_city()
вы можете работать пользовательскими данными, записать в бд и прочее.
Из-за этого вместо поиска введённого пользователем города в поиск отправлялась команда /start
. Отсюда и метод select()
не нашёл никаких элементов с соответствующим id
. Потому что на странице какая-то другая информация.
Во-вторых, проверяйте, что вам отвечает поиск Google, чтобы такие ошибки можно было как-то обработать.
В-третьих, найти элемент по id
можно несколько проще:
soup = bs4.BeautifulSoup(response.text, "html.parser")
temperature = soup.find(id="wob_tm").text
condition = soup.find(id='wob_dc').text
time = soup.find(id='wob_dts').text
print(temperature, condition, time)
Результат:
'2' 'Переменная облачность' 'суббота 02:00'
Если всё-таки нужно получить данные через метод select()
, то тогда нужно сделать через свойство text
:
soup.select('#wob_tm')[0].text
В-четвёртых, не используйте глобальные переменные в таком коде. Лучше создайте словарь, где ключом будет id
пользователя, а значением - его город. Так будет хоть какая-то возможность нормально работать с данными, ну а лучше всего подключить какую-нибудь базу данных, sqlite3, например.