PythonAnywhere部署Telegram Bot Webhook报Bad Request错误求助
解决PythonAnywhere上Telegram Bot Webhook的Bad Request错误
我帮你梳理下这个Bad Request问题的几个关键原因和解决办法,结合PythonAnywhere的部署特性来看,你的配置和代码里有几个容易踩的坑:
1. 冗余的HTTPS证书与端口配置
PythonAnywhere已经为你的username.pythonanywhere.com域名提供了官方可信的HTTPS证书,并且默认通过443端口对外提供服务,完全不需要你手动指定8443端口、加载本地证书文件。你的代码里的PORT、CERT、CERT_KEY配置,以及app.run中的context参数,在WSGI部署环境下完全无效,甚至可能干扰请求解析。
解决方式:
- 删除代码中所有与
PORT、CERT、CERT_KEY相关的变量和代码 - 调用
set_webhook时不需要传入certificate参数(Telegram信任PythonAnywhere的SSL证书)
2. Webhook未被实际设置
你的setwebhook()函数放在了if __name__ == '__main__'代码块中,但在PythonAnywhere的WSGI部署模式下,这个代码块永远不会执行(WSGI服务器是导入你的Flask app,而非直接运行脚本),导致Webhook根本没被正确配置。
解决方式:
你有两种可靠的设置Webhook的方法:
- 临时执行脚本:在PythonAnywhere的控制台中,进入项目目录,运行
python main.py,此时会执行if __name__ == '__main__'里的setwebhook(),看到提示后按Ctrl+C停止即可(WSGI服务已经在后台运行)。 - 手动调用:在PythonAnywhere的交互式Python控制台中,导入你的bot并手动设置Webhook:
from main import bot, HOST, TOKEN bot.set_webhook(url=f"https://{HOST}/{TOKEN}")
3. Flask路由与请求处理的细节优化
虽然你的路由逻辑看起来正确,但有两个细节需要调整:
- Telegram要求Webhook的响应必须是200 OK的简单文本(比如
'OK'),返回HTML可能不会触发错误,但没必要。 - 要处理可能的无效更新(比如非消息类型的更新,或者解析失败的请求),避免抛出异常导致500错误。
优化后的webhook_handler代码:
@app.route('/' + TOKEN, methods=['POST']) def webhook_handler(): try: update = telegram.Update.de_json(request.get_json(force=True), bot) # 只处理有消息的更新 if update.message: bot.send_message(chat_id=update.message.chat.id, text='Hello, there') return 'OK' except Exception as e: # 打印错误日志到PythonAnywhere的控制台 print(f"Error processing update: {str(e)}") # 无论如何都返回200 OK,避免Telegram重复发送请求 return 'OK', 200
4. 虚拟环境路径配置问题
你的代码中sys.path.append(os.path.join(os.path.abspath('.'), 'path/to/virtualenv/'))存在路径风险:在WSGI环境下,当前工作目录不一定是你的项目目录,相对路径可能无法正确指向虚拟环境。
更可靠的方式:
- 直接在PythonAnywhere的Web管理页面中,找到"Virtualenv"设置项,输入你的虚拟环境绝对路径(比如
/home/username/.virtualenvs/your_env),PythonAnywhere会自动将虚拟环境的site-packages加入sys.path,不需要手动在代码中添加。
修改后的完整代码示例
import sys from flask import Flask, request import telegram # CONFIG TOKEN = '<你的Bot Token>' HOST = 'username.pythonanywhere.com' bot = telegram.Bot(TOKEN) app = Flask(__name__) @app.route('/') def hello(): return '<h1> BITCONNECT!!! </h1>' @app.route('/' + TOKEN, methods=['POST']) def webhook_handler(): try: update = telegram.Update.de_json(request.get_json(force=True), bot) if update.message: bot.send_message(chat_id=update.message.chat.id, text='Hello, there') return 'OK' except Exception as e: print(f"Error processing update: {str(e)}") return 'OK', 200 def setwebhook(): bot.set_webhook(url=f"https://{HOST}/{TOKEN}") if __name__ == '__main__': setwebhook() print("Webhook set successfully!") # 本地测试时可以打开下面的注释,部署到PythonAnywhere后不需要 # app.run(host='0.0.0.0', debug=True)
内容的提问来源于stack exchange,提问作者Trafalgar Law




