Raspberry Pi Pico W中urequests请求返回400错误排查(requests正常)
问题:Raspberry Pi Pico W使用urequests请求瓦伦西亚地铁API返回400错误
我正在开发一款用于显示瓦伦西亚地铁时刻表的面板,计划使用Raspberry Pi Pico W和若干字符显示屏。
电脑端Python代码(使用requests库),运行正常返回200:
import requests url = 'https://www.metrovalencia.es/wp-admin/admin-ajax.php' myobj = {'action': 'formularios_ajax', 'data': f"action=horarios-ruta&\ origen=100&\ destino=101&\ dia=2022-11-12&\ horaDesde=10:00&\ horaHasta=23:59"} req = requests.post(url, data = myobj) print(req.status_code)
移植到Raspberry Pi Pico W后,使用urequests库的代码返回True(网络已连接)和400(请求失败):
import network import urequests import ujson wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect("SSID", "PASSW") ntptime.settime() print(wlan.isconnected()) url = 'https://www.metrovalencia.es/wp-admin/admin-ajax.php' myobj = {'action': 'formularios_ajax', 'data': f"action=horarios-ruta&\ origen=88&\ destino=91&\ dia=2022-11-12&\ horaDesde=10:00&\ horaHasta=23:59"} req = urequests.post(url, data = ujson.dumps(myobj)) print(req.status_code)
两处请求的URL和核心数据一致,请问该问题是由Raspberry Pi Pico限制、requests与urequests库差异还是缺少令牌导致的?
问题分析与解决
核心问题出在requests与urequests对POST数据的处理差异,以及请求头缺失:
数据编码方式不符
电脑端的requests.post(url, data=myobj)会自动把字典编码成application/x-www-form-urlencoded格式的表单数据,这是服务器预期的格式。但你在Pico代码里用ujson.dumps(myobj)把字典转成了JSON字符串,直接传给data参数后,请求的Content-Type变成了text/plain,服务器无法识别,所以返回400错误。缺少必要请求头
部分网站的AJAX接口会校验User-Agent等请求头,电脑端requests会自动添加默认的User-Agent,而urequests默认没有这一步,也可能触发服务器的拦截机制。
修正后的Pico W代码
import network import urequests import ntptime wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect("SSID", "PASSW") # 等待网络连接完成 while not wlan.isconnected(): pass ntptime.settime() print(wlan.isconnected()) url = 'https://www.metrovalencia.es/wp-admin/admin-ajax.php' # 直接构造表单格式的字符串,无需转JSON myobj = {'action': 'formularios_ajax', 'data': "action=horarios-ruta&origen=88&destino=91&dia=2022-11-12&horaDesde=10:00&horaHasta=23:59"} # 添加服务器需要的请求头 headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } req = urequests.post(url, data=myobj, headers=headers) print(req.status_code) # 可打印返回内容确认结果 # print(req.text) req.close() # 记得关闭请求释放资源
额外说明
- Raspberry Pi Pico W本身没有请求限制,和硬件无关。
- 当前不需要额外令牌,先按上述方式修正请求格式和头信息即可。如果仍失败,可以抓包对比电脑端和Pico端的请求细节,排查是否有其他缺失参数或头信息。
内容的提问来源于stack exchange,提问作者edoelas
相关产品推荐
相关产品推荐

