如何修复返回“Invalid JSON primitive: .”的POST请求
尝试通过POST请求爬取starbet.rs的投注数据时,返回Invalid JSON primitive: .错误。请求头和请求体均直接取自网站原有请求的cURL内容,修改POST返回类型后只能拿到网站HTML页面,无法获取目标JSON数据。
网站地址:https://www.starbet.rs/Bet
原代码:
import requests import json url = "https://www.starbet.rs/Oblozuvanje.aspx/GetLiga" payload = "{LigaID:^[494^],filter:0,parId:0}" ###LigaID is the ID of the chosen leagues not really of importance headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0", "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "application/json; charset=utf-8", "X-Requested-With": "XMLHttpRequest", "Origin": "https://www.starbet.rs", "DNT": "1", "Sec-GPC": "1", "Connection": "keep-alive", "Referer": "https://www.starbet.rs/Bet", "Cookie": "ASP.NET_SessionId=jsjbtw2gizig2sh3mfrrqyje; style=null", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "TE": "trailers" } response = requests.request("POST", url, data=payload, headers=headers) print(response.text)
错误信息(中文翻译):
"Message": "无效的JSON原语: .",
"StackTrace": "在 System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()\r\n 在 System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n 在 System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)\r\n 在 System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n 在 System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n 在 System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n 在 System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n 在 System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)",
"ExceptionType": "System.ArgumentException"
问题根源在于请求体的JSON格式不合法:
- 原payload中的
^[494^]是网站请求中的特殊编码,并非标准JSON格式,需要改成正常的数组[494] - JSON要求键名必须用双引号包裹,原payload的键名(如
LigaID)没有加双引号 - 使用
data参数传递字符串payload容易出现格式错误,推荐用json参数直接传递Python字典,requests会自动完成JSON序列化并设置正确的请求头
修改后的代码:
import requests url = "https://www.starbet.rs/Oblozuvanje.aspx/GetLiga" # 用Python字典构造合法的请求体,自动序列化为JSON payload = { "LigaID": [494], "filter": 0, "parId": 0 } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0", "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5", "X-Requested-With": "XMLHttpRequest", "Origin": "https://www.starbet.rs", "DNT": "1", "Sec-GPC": "1", "Connection": "keep-alive", "Referer": "https://www.starbet.rs/Bet", "Cookie": "ASP.NET_SessionId=jsjbtw2gizig2sh3mfrrqyje; style=null", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "TE": "trailers" } # 使用json参数传递payload,无需手动设置Content-Type(requests会自动处理) response = requests.post(url, json=payload, headers=headers) print(response.text)
关键改动说明
- 把字符串格式的payload改成Python字典,确保结构符合JSON规范
- 移除了原payload中的
^符号,将^[494^]修正为标准数组[494] - 用
requests.post替代requests.request,代码更简洁 - 使用
json参数传递请求体,替代data参数,避免手动构造JSON字符串的错误
内容的提问来源于stack exchange,提问作者ribicapongo

