我正在尝试将我的Wi-Fi SSID更改为表情符号,但web UI不允许它。相反,我将有效的PUT请求捕获到路由器的API,使用Chrome的开发工具将其复制为fetch
呼叫,将SSID更改为表情符号,然后重播请求。它很棒。
但是,当我尝试使用Python请求时,它会将表情符号(????
)转义为相应的JavaScript转义:\uD83E\uDD20
。当它被发送到路由器时,它会以某种方式转换为>
(大于符号后跟一个空格)。这是令人沮丧的,因为我假设两种方法都会以相同的方式编码表情符号。
由于它适用于JavaScript的fetch
,因此消息或表情符号的编码方式必须有所不同。
获取调用:(即使在使用Dev Tools检查请求时,表情符号也会显示为表情符号)(为简洁起见,编辑)
fetch("https://192.168.1.1/api/wireless", {
"credentials": "omit",
"headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8",
"x-xsrf-token": "[The token for this login session]"
},
"referrer": "https://192.168.1.1/",
"referrerPolicy": "no-referrer-when-downgrade",
"body": "{
\"wifi\": [{
\"boring key 1\": \"boring value\",
\"boring key 2\": \"boring value\",
\"ssid\": \"????\",
\"boring key 3\": \"boring value\",
\"boring key 4\": \"boring value\"
}]
}",
"method": "PUT",
"mode": "cors"
});
请求电话:(为简洁而编辑)
res = session.put('https://192.168.1.1/api/wireless',
verify=False,
json={
"wifi":[{
"boring key 1":"boring value",
"boring key 2":"boring value",
"ssid":"????",
"boring key 3":
"boring value",
"boring key 4":"boring value"
}]
})
那么他们被编码的方式有什么不同?我怎样才能看到fetch的实际输出是什么? (Dev Tools只显示一个表情符号,没有转义序列。)
分析解答
由requests
library中的json
参数完成的默认JSON处理基本上将ensure_ascii
设为True,以便提供这种类型的编码形式。基本上,put
调用将作为以下内容发送到服务器:
PUT / HTTP/1.1
Host: 192.168.1.1
User-Agent: python-requests/2.21.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 24
Content-Type: application/json
{"demo": "\ud83e\udd20"}
这不是你想要的。为了做你想做的事,你必须手动编码JSON并明确提供标题,如下所示:
requests.put(
'https://192.168.1.1',
data=json.dumps({"demo": "????"}, ensure_ascii=False).encode('utf8'),
headers={'Content-Type': 'application/json'},
)