Python requests请求报JSONDecodeError的修复方法
报错根因
你遇到的JSONDecodeError本质是接口返回了空内容/非JSON格式内容,不是合法的JSON结构,直接调用.json()必然解析失败,代码里一共存在5个直接触发问题的错误:
- 请求头里携带了
if-none-match缓存校验字段,服务器匹配到缓存标识时会直接返回304无内容响应,没有任何JSON数据返回 - 初始化了
requests.Session()会话对象但全程没有使用,所有POST/GET请求都是裸调用requests,会话Cookie、上下文鉴权信息完全不保留,很容易被接口鉴权拦截返回空内容/错误页 - 取接口返回的
data字段时错误写为response("data"),属于把字典当函数调用,就算JSON解析成功这行也会抛出类型错误 - 循环硬编码爬取1到1000页,没有做终止判断,当页码超过实际总页数时接口会返回空/错误结构,直接解析必然报错
- 代码开头对着带
%d占位符的未格式化URL直接发无效POST请求,完全没有实际作用,还可能触发接口风控
修复方案
按以下顺序调整代码即可正常抓取写入:
- 删掉headers里的
if-none-match字段,这个字段是浏览器缓存校验用,爬虫场景携带极易拿到空响应 - 所有接口请求统一用你初始化的Session对象
s发送,自动保留会话上下文、Cookie信息,降低被拦截概率 - 解析JSON前先校验响应状态码,增加异常捕获,遇到非200响应、非JSON返回时直接打印错误信息终止循环,不要硬解析
- 修正字段取值语法,把
response("data")改为response["data"],字段提取时增加容错,避免单个联系人缺失字段导致整个程序崩溃 - 增加翻页终止判断:当当前页返回的data为空列表时,说明已经爬完所有数据,直接跳出循环,不需要硬跑到1000页
- 删除开头那段无效的、对着未格式化URL发送的POST请求
修复后完整代码
import requests # 基础配置 base_url = "https://api-prod.grip.events/1/container/4368/search?search=&sort=name&order=asc&type_id=4907,4906,5265,4964,4904,1026,4908&page=%d" headers = { 'authority': 'api-prod.grip.events', 'accept': 'application/json', 'accept-language': 'en-gb', 'content-type': 'application/json', # 已删除if-none-match缓存头 'login-source': 'web', 'origin': 'https://connect.money2020.com', 'referer': 'https://connect.money2020.com/money2020europe/app/home/network/list/34589', 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'cross-site', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36', 'x-authorization': 'a422cc2a-31fb-4b4e-a1bd-a34b561adc6c', 'x-grip-version': 'Web/8.3.11', } s = requests.Session() # 会话预置headers,不用每次请求重复传 s.headers.update(headers) with open("list.txt", "w", encoding="utf-8") as f: for page in range(1, 1000): print(f"正在抓取第{page}页...") resp = s.get(base_url % page) # 先校验响应状态 if resp.status_code != 200: print(f"请求失败,状态码:{resp.status_code},响应内容:{resp.text[:200]}") break # 捕获JSON解析异常 try: resp_data = resp.json() except Exception as e: print(f"JSON解析失败,错误:{str(e)},响应内容:{resp.text[:200]}") break # 取当前页数据,为空则终止爬取 contacts = resp_data.get("data", []) if not contacts: print("所有页面抓取完成,程序终止") break # 遍历写入,增加字段容错 for contact in contacts: company_name = contact.get("company_name", "") job_title = contact.get("job_title", "") name = contact.get("name", "") job_industry = contact.get("job_industry", "") target = f"{company_name}\t{job_title}\t{name}\t{job_industry}" f.write(target + "\n") print(target)
注意事项
如果调整后依然返回解析错误,先检查x-authorization字段的token是否过期,token失效时接口会返回401/403状态码和非JSON的错误提示,替换成浏览器里最新的有效token即可。
内容的提问来源于stack exchange,提问作者Tori Elstrom
相关产品推荐
相关产品推荐

