如何解决Telegram API的telegram.error.BadRequest网页内容类型错误?
问题
我在PythonAnywhere服务器部署了一个Telegram天气机器人,支持返回2小时、24小时、4天三种天气预报。机器人调用新加坡政府天气API获取数据,整理为pandas DataFrame后保存为PNG图片,计划通过update.message.reply_photo(response)将图片发送给用户,其中response是PythonAnywhere上图片的HTTPS链接。本地运行时使用本地文件路径可正常工作,但在PythonAnywhere使用URL时出现telegram.error.BadRequest: Wrong type of the web page content错误,我怀疑是图片需要登录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文件管理页面URL需要登录验证,Telegram服务器访问时会被跳转到登录页面,返回的是HTML内容而非图片,因此触发Wrong type of the web page content错误。
具体解决方法
方法1:直接发送本地文件(推荐)
无需生成外部URL,直接将本地图片文件对象传给reply_photo,Telegram Bot API会自动处理上传:
- 修改
handle_response函数,返回本地文件路径而非URL:
以2小时预报分支为例,将return 'https://xxx...'改为return 'SG 2 hour weather.png',另外两个预报分支同理修改。 - 更新
handle_message函数,处理文件路径和错误提示:async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): text: str = update.message.text result = handle_response(text) if result.endswith('.png'): with open(result, 'rb') as photo_file: await update.message.reply_photo(photo_file) else: await update.message.reply_text(result)
方法2:配置PythonAnywhere静态文件服务
如果坚持使用URL访问图片,需在PythonAnywhere设置静态文件目录:
- 进入PythonAnywhere的「Web」页面,找到「Static files」板块。
- 添加静态文件映射:
- URL:填写
/static/ - Directory:填写图片存放的绝对路径(如
/home/<你的用户名>/)
- URL:填写
- 保存后,图片的公开访问URL为
https://<你的用户名>.pythonanywhere.com/static/SG 2 hour weather.png - 建议将文件名中的空格改为下划线(如
SG_2_hour_weather.png),避免URL编码问题。
额外优化建议
- 生成图片时使用绝对路径,避免路径歧义:比如
filename='/home/<你的用户名>/SG_2_hour_weather.png' - 可给文件名添加时间戳,避免重复生成图片时的文件覆盖问题。
内容的提问来源于stack exchange,提问作者appleseed09
相关产品推荐
相关产品推荐

