如何正确解析被 HTML 实体编码的嵌套 JSON 字段
技术百科
碧海醫心
发布时间:2026-01-27
浏览: 次 当 api 返回的 json 中某些字段(如 `child_sku_options`)实际是经过 html 实体编码的 json 字符串时,直接 `json.loads()` 会失败;需先用 `html.unescape()` 还原转义字符,再二次解析。
在调用某些搜索服务(如 SearchSpring)的 API 时,常见一种“伪嵌套 JSON”现象:主响应是合法 JSON,但其中某个字符串字段(例如 "child_sku_options")的值并非原始 JSON 对象,而是被双重编码的 JSON 字符串——它被 HTML 实体转义(如 \/ 代替 /、" 替代 "),导致直接解析报错或输出乱码。
你的原始代码:
print(json.loads(response.content))
看似合理,但问题出在 response.content 解析后得到的 data["results"][i]["child_sku_options"] 是一个字符串形式的、被 HTML 转义的 JSON,例如:
"{\"option_value_id\":197674,\"value\":\"12 Degree\",...\"image_url\":\"https:\\/\\/cdn11.bigcommerce.com\\/...jpg\"}"该字符串中的 \/ 和 \" 是 HTML/XML 编码结果,并非标准 JSON 允许的原始反斜杠,因此无法被 json.loads() 直接识别。
✅ 正确处理流程如下:
- 先解析顶层 JSON:使用 response.json() 或 json.loads(response.content) 获取主数据结构;
- 定位被编码的字段:如 r["child_sku_options"](类型为 str);
- HTML 解码:调用 html.unescape() 消除 "、/、\/ 等转义,还原为标准 JSON 字符串;
- 二次 JSON 解析:对解码后的字符串执行 json.loads(),得到真正的 Python 字典/列表。
以下是完整、健壮的示例代码(含错误处理和推荐实践):
import json
import requests
from html import unescape
url = "https://547os1.a.searchspring.io/api/search/search.json?ajaxCatalog=v3&resultsFormat=native&siteId=547os1&domain=https%3A%2F%2Fwww.golfbox.com.au%2Fsearch%3Fq%3DCalaway%2BParadym%2BDriver%26Search%3DSEARCH&q=Calaway%20Paradym%20Driver"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
}
try:
response = requests.get(url, headers=headers, timeout=10, verify=False)
response.raise_for_status() # 检查 HTTP 错误状态码
# 解析顶层 JSON
data = response.json()
# 遍历搜索结果,提取并解析 child_sku_options
for i, result in enumerate(data.get("results", [])):
options_str = result.get("child_sku_options")
if not isinstance(options_str, str) or not options_str.strip():
print(f"[跳过] 第 {i+1} 条结果无 child_sku_options 字段")
continue
try:
# 步骤1:HTML 解码 → 还原为标准 JSON 字符串
decoded_str = unescape(options_str)
# 步骤2:JSON 解析 → 转为 Python 对象
options_list = json.loads(decoded_str)
print(f"✅ 第 {i+1} 条结果解析成功,共 {len(options_list)} 个 SKU 选项:")
# 示例:打印首个选项的 child_sku 和 price
if options_list:
first = options_list[0]
print(f" - SKU: {first.get('child_sku', 'N/A')}, Price: ${first.get('price', 'N/A')}")
except json.JSONDecodeError as e:
print(f"❌ 解析第 {i+1} 条的 child_sku_options 失败:{e}")
print(f" 原始字符串(截取前100字符):{options_str[:100]}...")
except Exception as e:
print(f"⚠️ 其他异常:{e
}")
except requests.exceptions.RequestException as e:
print(f"网络请求失败:{e}")
except json.JSONDecodeError as e:
print(f"顶层 JSON 解析失败:{e}")? 关键注意事项:
- ❌ 不要禁用 SSL 验证(verify=False)用于生产环境——它会带来安全风险。如遇证书问题,请更新 CA 证书或使用 requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS 调整 TLS 设置,而非关闭验证。
- ✅ 优先使用 response.json() 而非 json.loads(response.content),前者自动处理编码(如 UTF-8 BOM、Content-Type charset),更可靠。
- ✅ 始终校验字段是否存在(dict.get())、类型是否正确(isinstance(..., str)),避免 KeyError 或 TypeError。
- ? 若发现 unescape() 后仍解析失败,可用 print(repr(decoded_str)) 查看真实字符串内容,确认是否含不可见控制字符(如 \u2028 行分隔符),必要时用正则清洗。
通过这一“HTML 解码 + 二次 JSON 解析”的组合策略,你就能稳定提取 SearchSpring 等平台返回的嵌套结构化商品选项数据,彻底告别 \/ 和 " 带来的解析困扰。
# ai
# 搜索结果
# 就能
# 是一个
# 这一
# 它会
# python
# safari
# windows
# 而非
# app
# 数据结构
# win
# js
# json
# go
# 对象
# html
# 编码
# xml
# 字符串
# 报错
# bom
# ssl
# 遍历
# print
# ajax
# 原为
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么关闭系统推荐内容_Windows11
- c++输入输出流 c++ cin与cout格式化输
- 如何从 Go 的 map[string]inter
- php查询数据怎么分组_groupby分组查询配合
- mac怎么分屏_MAC双屏显示与分屏操作技巧【指南
- Win11怎么设置任务栏透明_Windows11使
- Go 中实现 Python urllib.quot
- Win11怎么清理C盘系统日志_Win11清理系统
- Python性能剖析高级教程_cProfileLi
- 如何使用Golang table-driven基准
- 如何将文本文件中的竖排字符串转换为横排字符串
- Win11截图快捷键是什么_Win11自带截图工具
- c# 如何深拷贝和浅拷贝
- Win10闹钟铃声怎么自定义 Win10闹钟自定义
- php怎么捕获异常_trycatch结构处理运行时
- 如何在 Go 中创建包含 map 的 slice(
- 如何在Golang中使用time处理时间_Gola
- mac怎么安装adb_MAC配置Android A
- Python模块的__name__属性如何由导入方
- c++如何连接Redis c++ hiredis库
- VSC怎么在PHP中调试MySQL_数据库交互排查
- 如何使用Golang管理跨项目依赖_Golang多
- 如何使用Golang理解结构体指针方法接收者_Go
- c++中如何计算坐标系中两点间距离_c++勾股定理
- c++如何用AFL++进行模糊测试 c++ Fuz
- Win11怎么关闭触摸屏_禁用Win11笔记本触摸
- C#如何使用XPathNavigator高效查询X
- How to Properly Use NumPy
- php删除数据怎么加限制_带where条件删除避免
- MAC怎么截图并快速编辑_MAC自带截图快捷键与标
- Win11怎么设置ip地址_Windows 11手
- php8.4如何实现队列任务_php8.4redi
- Python网页解析流程_html结构说明【指导】
- Python与GPU加速技术_CUDA与Numba
- Win10如何备份驱动程序_Win10驱动备份步骤
- Win11如何更改任务栏颜色 Win11自定义任务
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- 如何使用Golang sort排序切片_Golan
- Windows7怎么找回经典开始菜单_Window
- Python对象比较与排序_集合使用说明【指导】
- Win11时间格式怎么改成12小时制 Win11时
- php错误怎么开启_display_errors与
- Python脚本参数接收_sys与argparse
- php做exe支持多线程吗_并发处理实现方式【详解
- Python邮件系统自动化教程_批量发送解析与模板
- 如何使用Golang指针与接口结合_实现方法调用和
- Windows服务无法启动错误1067是什么_进程
- Win11怎么更改任务栏位置_修改注册表将Win1
- 如何关闭Win10自动更新更新_Win10系统自动
- Win10系统更新错误0x80240034怎么办


QQ客服