我编写了一个脚本来对 Telegram 机器人进行编程,以根据用户的选择将天气预报信息返回给用户。有 3 个选项: (1) 2 小时预报; (2)24小时预报; (3) 4 天预测。该脚本驻留在 pythonanywhere 服务器上。
该脚本将调用天气预报网站的 API 来获取信息。
然后将信息合并到 pandas 数据框中,然后将其保存为 png 文件。
目的是让 Telegram 机器人使用
update.message.reply_photo(response)
将 png 文件发送回用户。 response
是一个 HTTPS 链接,可打开保存在 pythonanywhere 服务器上的图像。
运行脚本后,我遇到了
telegram.error.BadRequest: Wrong type of the web page content
错误。我对此感到困惑,因为 Telegram API 文档指出 URL 被接受作为参数。
我已经在下面包含了我的脚本和回溯消息。我故意屏蔽了我的 API 令牌和用户名。这被替换为
<purposely_masked_out>
。
仅供参考:我已经在本地计算机上运行了该脚本并且运行良好。 pythonanywhere 上托管的脚本(给我错误的脚本)与本地计算机上的脚本之间的区别在于传递给
update.message.reply_photo(response)
的参数。区别如下:
*本地计算机:脚本将 png 文件保存在我的桌面上,响应指的是 png 的文件名。
Pythonanywhere:脚本将 png 文件保存在我的 pythonanywhere 文件夹中,响应引用了 png 的 URL。我不确定是否是因为该文件需要登录 pythonanywhere 才能访问它。*
请帮忙。
**我的脚本:**
import requests
import pandas as pd
import json
from typing import Final
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
import df2img
BOT_TOKEN: Final = <purposely_masked_out>
BOT_USERNAME: Final = <purposely_masked_out>
async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text('Hi! You can check the SG weather by typing \'2 hours\', \'24 hours\' or \'4 days\'')
def handle_response(text: str) -> str:
# 2 hours weather data extraction
if '2 hours' in text:
two_r = requests.get('https://api.data.gov.sg/v1/environment/2-hour-weather-forecast').json()
two_df = pd.DataFrame(columns=['area', 'forecast'])
for i in range(len(two_r['items'][0]['forecasts'])):
two_df.loc[i] = [(two_r['items'][0]['forecasts'][i]['area']),
(two_r['items'][0]['forecasts'][i]['forecast'])]
fig = df2img.plot_dataframe(two_df)
df2img.save_dataframe(fig=fig, filename='SG 2 hour weather.png')
return 'https://www.pythonanywhere.com/user/<purposely_masked_out>/files/home/<purposely_masked_out>/SG 2 hour weather.png'
# 24 hours weather data extraction
elif '24 hours' in text:
two_four_r = requests.get('https://api.data.gov.sg/v1/environment/24-hour-weather-forecast').json()
# compiling the forecast data
forecast = list(two_four_r['items'][0]['periods'][0]['regions'].values())
temp_list = []
for i in range(1, 3):
temp_list.extend(list(two_four_r['items'][0]['periods'][i]['regions'].values()))
for x in range(len(temp_list)):
forecast.append(temp_list[x])
# compiling the region data
region = list(two_four_r['items'][0]['periods'][0]['regions'].keys()) * 3
# compiling the period data
period = ['first 8 hours'] * 5 + ['next 8 hours'] * 5 + ['subsequent 8 hours'] * 5
# compiling all 3 above together
d = {}
d['forecast'] = forecast
d['region'] = region
d['period'] = period
# convert into a dataframe for extraction
two_four_df = pd.DataFrame(d)
two_four_df = two_four_df[['period', 'region', 'forecast']]
fig = df2img.plot_dataframe(two_four_df)
df2img.save_dataframe(fig=fig, filename='SG 24 hour weather.png')
return 'https://www.pythonanywhere.com/user/<purposely_masked_out>/files/home/<purposely_masked_out>/SG 24 hour weather.png'
# 4 days weather data extraction
elif '4 days' in text:
four_day_r = requests.get('https://api.data.gov.sg/v1/environment/4-day-weather-forecast').json()
four_day_df = pd.DataFrame(columns=['forecast'])
for i in range(4):
four_day_df.loc[i] = [four_day_r['items'][0]['forecasts'][i]['forecast']]
fig = df2img.plot_dataframe(four_day_df)
df2img.save_dataframe(fig=fig, filename='SG 4 days weather.png')
return 'https://www.pythonanywhere.com/user/<purposely_masked_out>/files/home/<purposely_masked_out>/SG 4 day weather.png'
else:
return 'I don\'t understand. Please select between \'2 hours\', \'24 hours\' or \'4 days\' and type them properly without spacing'
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
text: str = update.message.text
response = handle_response(text)
await update.message.reply_photo(response)
if __name__ == '__main__':
print('Starting bot...')
app = Application.builder().token(BOT_TOKEN).build()
app.add_handler(CommandHandler('start', start_command))
app.add_handler(MessageHandler(filters.TEXT, handle_message))
print('Polling...')
app.run_polling(poll_interval=3)
追溯消息:
No error handlers are registered, logging exception.
Traceback (most recent call last):
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/ext/_application.py", line 1184, in process_update
await coroutine
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/ext/_basehandler.py", line 141, in handle_update
return await self.callback(update, context)
File "/home/<purposely_masked_out>/sg-weather-telegram-bot.py", line 89, in handle_message
await update.message.reply_photo(response)
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/_message.py", line 1391, in reply_photo
return await self.get_bot().send_photo(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/ext/_extbot.py", line 2655, in send_photo
return await super().send_photo(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/_bot.py", line 394, in decorator
result = await func(self, *args, **kwargs) # skipcq: PYL-E1102
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/_bot.py", line 1055, in send_photo
return await self._send_message(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/ext/_extbot.py", line 517, in _send_message
result = await super()._send_message(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/_bot.py", line 572, in _send_message
result = await self._post(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/_bot.py", line 482, in _post
return await self._do_post(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/ext/_extbot.py", line 335, in _do_post
return await super()._do_post(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/_bot.py", line 510, in _do_post
return await request.post(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/request/_baserequest.py", line 168, in post
result = await self._request_wrapper(
File "/home/<purposely_masked_out>/.local/lib/python3.10/site-packages/telegram/request/_baserequest.py", line 325, in _request_wrapper
raise BadRequest(message)
telegram.error.BadRequest: Wrong type of the web page content
我不确定是否是因为该文件需要登录 pythonanywhere 访问它
确实如此——在 PythonAnywhere 上,像
https://www.pythonanywhere.com/user/username/files/...
这样的 url 只能由登录用户 username
通过浏览器访问。如果您想以编程方式共享文件,您需要相应地提供它们。