使用urllib向Google Hangouts Chat机器人发消息遇400错误求助
这种问题在从封装性强的库(比如httplib2)切换到标准库urllib时很常见——毕竟httplib2会帮你自动处理不少请求细节,而urllib需要你手动把控每一步。我整理了几个最可能的原因和对应的解决方法:
1. 缺少Content-Type: application/json请求头
Hangouts Chat的Webhook明确要求请求必须携带这个头,它告诉服务器你发送的是JSON格式的数据。httplib2在发送JSON数据时通常会自动帮你设置这个头,但urllib不会。如果漏掉它,服务器无法识别请求内容的格式,直接返回400错误。
解决方法:手动添加请求头,示例代码如下:
import urllib.request import json webhook_url = "你的Webhook地址" message = {"text": "Hello from urllib!"} # 必须添加Content-Type头 headers = { 'Content-Type': 'application/json', } # 序列化数据并编码为bytes(urllib要求的格式) json_data = json.dumps(message).encode('utf-8') req = urllib.request.Request(webhook_url, data=json_data, headers=headers) response = urllib.request.urlopen(req)
2. 数据未正确序列化或编码
urllib的Request对象要求data参数是bytes类型的数据流。很多人会犯两个错误:要么直接把Python字典传给data,要么用json.dumps()序列化后没转成bytes,这都会导致请求格式错误。
常见错误示例:
# 错误:直接传Python字典,urllib无法处理 req = urllib.request.Request(webhook_url, data=message, headers=headers) # 错误:序列化后未编码为bytes json_data = json.dumps(message) req = urllib.request.Request(webhook_url, data=json_data, headers=headers)
正确做法:先用json.dumps()把字典转成JSON字符串,再用.encode('utf-8')转成bytes,就像上面的示例那样。
3. JSON消息格式不符合要求
虽然你用httplib2成功过,但切换到urllib时可能不小心修改了消息结构(比如拼写错误,把text写成message,或者嵌套结构出错)。Hangouts Chat对消息格式有严格要求,最基础的消息必须包含text字段。
验证方法:打印json.dumps(message)的结果,检查是否符合官方要求的格式。比如基础消息格式应该是:
{"text": "Hello, World!"}
如果消息里缺少必要字段或者有多余的无效字段,服务器会直接返回400。
4. 手动拼接JSON导致的语法错误
如果图省事手动拼接JSON字符串(而不是用json.dumps()),很容易因为特殊字符(比如双引号、斜杠)未转义导致JSON语法错误,服务器解析失败后返回400。
错误示例:
# 手动拼接JSON,双引号未转义,导致语法错误 message_str = '{"text": "He said "Hello!" to me"}' json_data = message_str.encode('utf-8')
正确做法:始终用json.dumps()来序列化Python对象,它会自动处理特殊字符的转义,避免语法错误。
内容的提问来源于stack exchange,提问作者fredrik

